├── .gitignore
├── LICENSE
├── README.md
├── UwpMessageRelay.Consumer
├── App.xaml
├── App.xaml.cs
├── Assets
│ ├── LockScreenLogo.scale-200.png
│ ├── SplashScreen.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── StoreLogo.png
│ └── Wide310x150Logo.scale-200.png
├── MainPage.xaml
├── MainPage.xaml.cs
├── Package.appxmanifest
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── Services
│ └── MessageRelayService.cs
├── UwpMessageRelay.Consumer.csproj
├── UwpMessageRelay.Consumer_TemporaryKey.pfx
├── project.json
└── project.lock.json
├── UwpMessageRelay.MessageRelay.sln
├── UwpMessageRelay.MessageRelay
├── Assets
│ ├── LockScreenLogo.scale-200.png
│ ├── SplashScreen.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── StoreLogo.png
│ └── Wide310x150Logo.scale-200.png
├── Package.appxmanifest
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── StartupTask.cs
├── UwpMessageRelay.MessageRelay.csproj
├── UwpMessageRelay.MessageRelay_TemporaryKey.pfx
├── project.json
└── project.lock.json
└── UwpMessageRelay.Producer
├── App.xaml
├── App.xaml.cs
├── Assets
├── LockScreenLogo.scale-200.png
├── SplashScreen.scale-200.png
├── Square150x150Logo.scale-200.png
├── Square44x44Logo.scale-200.png
├── Square44x44Logo.targetsize-24_altform-unplated.png
├── StoreLogo.png
└── Wide310x150Logo.scale-200.png
├── MainPage.xaml
├── MainPage.xaml.cs
├── Package.appxmanifest
├── Properties
├── AssemblyInfo.cs
└── Default.rd.xml
├── Services
└── MessageRelayService.cs
├── UwpMessageRelay.Producer.csproj
├── UwpMessageRelay.Producer_TemporaryKey.pfx
├── project.json
└── project.lock.json
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Visual Studio
3 | #################
4 |
5 | ## Ignore Visual Studio temporary files, build results, and
6 | ## files generated by popular Visual Studio add-ons.
7 |
8 | # User-specific files
9 | *.suo
10 | *.user
11 | *.sln.docstates
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Rr]elease/
16 | *_i.c
17 | *_p.c
18 | *.ilk
19 | *.meta
20 | *.obj
21 | *.pch
22 | *.pdb
23 | *.pgc
24 | *.pgd
25 | *.rsp
26 | *.sbr
27 | *.tlb
28 | *.tli
29 | *.tlh
30 | *.tmp
31 | *.vspscc
32 | .builds
33 | *.dotCover
34 |
35 | packages/
36 |
37 | # Visual C++ cache files
38 | ipch/
39 | *.aps
40 | *.ncb
41 | *.opensdf
42 | *.sdf
43 |
44 | # Visual Studio profiler
45 | *.psess
46 | *.vsp
47 |
48 | # ReSharper is a .NET coding add-in
49 | _ReSharper*
50 |
51 | # Installshield output folder
52 | [Ee]xpress
53 |
54 | # DocProject is a documentation generator add-in
55 | DocProject/buildhelp/
56 | DocProject/Help/*.HxT
57 | DocProject/Help/*.HxC
58 | DocProject/Help/*.hhc
59 | DocProject/Help/*.hhk
60 | DocProject/Help/*.hhp
61 | DocProject/Help/Html2
62 | DocProject/Help/html
63 |
64 | # Click-Once directory
65 | publish
66 |
67 | # Others
68 | [Bb]in
69 | [Oo]bj
70 | sql
71 | TestResults
72 | *.Cache
73 | ClientBin
74 | stylecop.*
75 | ~$*
76 | *.dbmdl
77 | Generated_Code #added for RIA/Silverlight projects
78 |
79 | # Backup & report files from converting an old project file to a newer
80 | # Visual Studio version. Backup files are not needed, because we have git ;-)
81 | _UpgradeReport_Files/
82 | Backup*/
83 | UpgradeLog*.XML
84 |
85 |
86 |
87 | ############
88 | ## Windows
89 | ############
90 |
91 | # Windows image file caches
92 | Thumbs.db
93 |
94 | # Folder config file
95 | Desktop.ini
96 |
97 | ############
98 | ## NCrunch
99 | ############
100 |
101 | *.ncrunchsolution
102 | *.ncrunchproject
103 |
104 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Lee Richardson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UwpMessageRelay
2 | A sample UWP app demonstrating how to use AppServiceConnection to do interprocess communication
3 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using Windows.ApplicationModel;
4 | using Windows.ApplicationModel.Activation;
5 | using Windows.UI.Xaml;
6 | using Windows.UI.Xaml.Controls;
7 | using Windows.UI.Xaml.Navigation;
8 | using UwpMessageRelay.Consumer.Services;
9 |
10 | namespace UwpMessageRelay.Consumer
11 | {
12 | ///
13 | /// Provides application-specific behavior to supplement the default Application class.
14 | ///
15 | sealed partial class App
16 | {
17 | private readonly MessageRelayService _connection = MessageRelayService.Instance;
18 |
19 | ///
20 | /// Initializes the singleton application object. This is the first line of authored code
21 | /// executed, and as such is the logical equivalent of main() or WinMain().
22 | ///
23 | public App()
24 | {
25 | InitializeComponent();
26 | Suspending += OnSuspending;
27 | LeavingBackground += OnLeavingBackground;
28 | }
29 |
30 | private async void OnLeavingBackground(object sender, LeavingBackgroundEventArgs leavingBackgroundEventArgs)
31 | {
32 | try
33 | {
34 | await _connection.Open();
35 | }
36 | catch (Exception ex)
37 | {
38 | // failing quietly is probably ok for now since the connection will
39 | // attempt to re-open itself again on next send. It just means
40 | // we won't be able to receive messages
41 | Debug.WriteLine("Error opening connection on startup" + ex);
42 | }
43 | }
44 |
45 | ///
46 | /// Invoked when the application is launched normally by the end user. Other entry points
47 | /// will be used such as when the application is launched to open a specific file.
48 | ///
49 | /// Details about the launch request and process.
50 | protected override void OnLaunched(LaunchActivatedEventArgs e)
51 | {
52 | #if DEBUG
53 | if (Debugger.IsAttached)
54 | {
55 | DebugSettings.EnableFrameRateCounter = true;
56 | }
57 | #endif
58 | Frame rootFrame = Window.Current.Content as Frame;
59 |
60 | // Do not repeat app initialization when the Window already has content,
61 | // just ensure that the window is active
62 | if (rootFrame == null)
63 | {
64 | // Create a Frame to act as the navigation context and navigate to the first page
65 | rootFrame = new Frame();
66 |
67 | rootFrame.NavigationFailed += OnNavigationFailed;
68 |
69 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
70 | {
71 | //TODO: Load state from previously suspended application
72 | }
73 |
74 | // Place the frame in the current Window
75 | Window.Current.Content = rootFrame;
76 | }
77 |
78 | if (e.PrelaunchActivated == false)
79 | {
80 | if (rootFrame.Content == null)
81 | {
82 | // When the navigation stack isn't restored navigate to the first page,
83 | // configuring the new page by passing required information as a navigation
84 | // parameter
85 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
86 | }
87 | // Ensure the current window is active
88 | Window.Current.Activate();
89 | }
90 | }
91 |
92 | ///
93 | /// Invoked when Navigation to a certain page fails
94 | ///
95 | /// The Frame which failed navigation
96 | /// Details about the navigation failure
97 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
98 | {
99 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
100 | }
101 |
102 | ///
103 | /// Invoked when application execution is being suspended. Application state is saved
104 | /// without knowing whether the application will be terminated or resumed with the contents
105 | /// of memory still intact.
106 | ///
107 | /// The source of the suspend request.
108 | /// Details about the suspend request.
109 | private void OnSuspending(object sender, SuspendingEventArgs e)
110 | {
111 | var deferral = e.SuspendingOperation.GetDeferral();
112 |
113 | _connection.CloseConnection();
114 |
115 | deferral.Complete();
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Consumer/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Consumer/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Consumer/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Consumer/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Consumer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Consumer/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Consumer/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Message results
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using Windows.Foundation.Collections;
5 | using Windows.UI.Xaml;
6 | using UwpMessageRelay.Consumer.Services;
7 |
8 | // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
9 |
10 | namespace UwpMessageRelay.Consumer
11 | {
12 | ///
13 | /// An empty page that can be used on its own or navigated to within a Frame.
14 | ///
15 | public sealed partial class MainPage
16 | {
17 | private readonly MessageRelayService _connection = MessageRelayService.Instance;
18 |
19 | public MainPage()
20 | {
21 | InitializeComponent();
22 | Loaded += OnLoaded;
23 | _connection.OnMessageReceived += ConnectionOnMessageReceived;
24 | }
25 |
26 | private async void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
27 | {
28 | await EnsureConnected();
29 | }
30 |
31 | private async Task EnsureConnected()
32 | {
33 | var retryDelay = 10000;
34 | await Task.Delay(retryDelay);
35 | while (!_connection.IsConnected)
36 | {
37 | try
38 | {
39 | await _connection.Open();
40 | }
41 | catch (Exception)
42 | {
43 | // note ensure MessageRelay is deployed by right clicking on UwpMessageRelay.MessageRelay and selecting "Deploy"
44 | MessageResults.Text = $"Unable to connect to siren of shame engine. Retrying in {(retryDelay / 1000)} seconds...";
45 | await Task.Delay(retryDelay);
46 | }
47 | }
48 | }
49 |
50 | private async void ConnectionOnMessageReceived(ValueSet valueSet)
51 | {
52 | await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
53 | {
54 | var message = valueSet.First();
55 | MessageResults.Text = $"{message.Value}";
56 | });
57 | }
58 |
59 | private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
60 | {
61 | MessageResults.Text = "Sending Message";
62 | try
63 | {
64 | await _connection.SendMessageAsync("Echo", Message.Text);
65 | MessageResults.Text = "Message Sent Successfully";
66 | }
67 | catch (Exception ex)
68 | {
69 | MessageResults.Text = "Send error: " + ex.Message;
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | UwpMessageRelay.Consumer
18 | Lee
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UwpMessageRelay.Consumer")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UwpMessageRelay.Consumer")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/Services/MessageRelayService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using Windows.ApplicationModel.AppService;
5 | using Windows.Foundation.Collections;
6 |
7 | namespace UwpMessageRelay.Consumer.Services
8 | {
9 | public class MessageRelayService
10 | {
11 | const string AppServiceName = "UwpMessageRelayService";
12 | private AppServiceConnection _connection;
13 | public event Action OnMessageReceived;
14 |
15 | // Todo: convert to dependency injection
16 | public static MessageRelayService Instance { get; } = new MessageRelayService();
17 | public bool IsConnected => _connection != null;
18 |
19 | private async Task CachedConnection()
20 | {
21 | if (_connection != null) return _connection;
22 | _connection = await MakeConnection();
23 | _connection.RequestReceived += ConnectionOnRequestReceived;
24 | _connection.ServiceClosed += ConnectionOnServiceClosed;
25 | return _connection;
26 | }
27 |
28 | public async Task Open()
29 | {
30 | await CachedConnection();
31 | }
32 |
33 | private async Task MakeConnection()
34 | {
35 | var listing = await AppServiceCatalog.FindAppServiceProvidersAsync(AppServiceName);
36 |
37 | if (listing.Count == 0)
38 | {
39 | throw new Exception("Unable to find app service '" + AppServiceName + "'");
40 | }
41 | var packageName = listing[0].PackageFamilyName;
42 |
43 | var connection = new AppServiceConnection
44 | {
45 | AppServiceName = AppServiceName,
46 | PackageFamilyName = packageName
47 | };
48 |
49 | var status = await connection.OpenAsync();
50 |
51 | if (status != AppServiceConnectionStatus.Success)
52 | {
53 | throw new Exception("Could not connect to MessageRelay, status: " + status);
54 | }
55 |
56 | return connection;
57 | }
58 |
59 | private void ConnectionOnServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
60 | {
61 | DisposeConnection();
62 | }
63 |
64 | private void DisposeConnection()
65 | {
66 | if (_connection == null) return;
67 |
68 | _connection.RequestReceived -= ConnectionOnRequestReceived;
69 | _connection.ServiceClosed -= ConnectionOnServiceClosed;
70 | _connection.Dispose();
71 | _connection = null;
72 | }
73 |
74 | private void ConnectionOnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
75 | {
76 | var appServiceDeferral = args.GetDeferral();
77 | try
78 | {
79 | ValueSet valueSet = args.Request.Message;
80 | OnMessageReceived?.Invoke(valueSet);
81 | }
82 | finally
83 | {
84 | appServiceDeferral.Complete();
85 | }
86 | }
87 |
88 | public void CloseConnection()
89 | {
90 | DisposeConnection();
91 | }
92 |
93 | private async Task SendMessageAsync(KeyValuePair keyValuePair)
94 | {
95 | var connection = await CachedConnection();
96 | var result = await connection.SendMessageAsync(new ValueSet { keyValuePair });
97 | if (result.Status == AppServiceResponseStatus.Success)
98 | {
99 | return;
100 | }
101 | throw new Exception("Error sending " + result.Status);
102 | }
103 |
104 | public async Task SendMessageAsync(string key, string value)
105 | {
106 | await SendMessageAsync(new KeyValuePair(key, value));
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/UwpMessageRelay.Consumer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}
8 | AppContainerExe
9 | Properties
10 | UwpMessageRelay.Consumer
11 | UwpMessageRelay.Consumer
12 | en-US
13 | UAP
14 | 10.0.14393.0
15 | 10.0.10586.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | UwpMessageRelay.Consumer_TemporaryKey.pfx
20 |
21 |
22 | true
23 | bin\x86\Debug\
24 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
25 | ;2008
26 | full
27 | x86
28 | false
29 | prompt
30 | true
31 |
32 |
33 | bin\x86\Release\
34 | TRACE;NETFX_CORE;WINDOWS_UWP
35 | true
36 | ;2008
37 | pdbonly
38 | x86
39 | false
40 | prompt
41 | true
42 | true
43 |
44 |
45 | true
46 | bin\ARM\Debug\
47 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
48 | ;2008
49 | full
50 | ARM
51 | false
52 | prompt
53 | true
54 |
55 |
56 | bin\ARM\Release\
57 | TRACE;NETFX_CORE;WINDOWS_UWP
58 | true
59 | ;2008
60 | pdbonly
61 | ARM
62 | false
63 | prompt
64 | true
65 | true
66 |
67 |
68 | true
69 | bin\x64\Debug\
70 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
71 | ;2008
72 | full
73 | x64
74 | false
75 | prompt
76 | true
77 |
78 |
79 | bin\x64\Release\
80 | TRACE;NETFX_CORE;WINDOWS_UWP
81 | true
82 | ;2008
83 | pdbonly
84 | x64
85 | false
86 | prompt
87 | true
88 | true
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | App.xaml
97 |
98 |
99 | MainPage.xaml
100 |
101 |
102 |
103 |
104 |
105 |
106 | Designer
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | MSBuild:Compile
123 | Designer
124 |
125 |
126 | MSBuild:Compile
127 | Designer
128 |
129 |
130 |
131 | 14.0
132 |
133 |
134 |
141 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/UwpMessageRelay.Consumer_TemporaryKey.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Consumer/UwpMessageRelay.Consumer_TemporaryKey.pfx
--------------------------------------------------------------------------------
/UwpMessageRelay.Consumer/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.1.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UwpMessageRelay.MessageRelay", "UwpMessageRelay.MessageRelay\UwpMessageRelay.MessageRelay.csproj", "{2E51632E-E824-4A35-B0E0-8757DE421C24}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UwpMessageRelay.Producer", "UwpMessageRelay.Producer\UwpMessageRelay.Producer.csproj", "{7604B769-C16A-470F-8239-BD83149E972A}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UwpMessageRelay.Consumer", "UwpMessageRelay.Consumer\UwpMessageRelay.Consumer.csproj", "{6563F4FE-24A3-43EF-AE3F-D53F17929DAF}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|ARM = Debug|ARM
15 | Debug|x64 = Debug|x64
16 | Debug|x86 = Debug|x86
17 | Release|ARM = Release|ARM
18 | Release|x64 = Release|x64
19 | Release|x86 = Release|x86
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|ARM.ActiveCfg = Debug|ARM
23 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|ARM.Build.0 = Debug|ARM
24 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|ARM.Deploy.0 = Debug|ARM
25 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|x64.ActiveCfg = Debug|x64
26 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|x64.Build.0 = Debug|x64
27 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|x64.Deploy.0 = Debug|x64
28 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|x86.ActiveCfg = Debug|x86
29 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|x86.Build.0 = Debug|x86
30 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Debug|x86.Deploy.0 = Debug|x86
31 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|ARM.ActiveCfg = Release|ARM
32 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|ARM.Build.0 = Release|ARM
33 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|ARM.Deploy.0 = Release|ARM
34 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|x64.ActiveCfg = Release|x64
35 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|x64.Build.0 = Release|x64
36 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|x64.Deploy.0 = Release|x64
37 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|x86.ActiveCfg = Release|x86
38 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|x86.Build.0 = Release|x86
39 | {2E51632E-E824-4A35-B0E0-8757DE421C24}.Release|x86.Deploy.0 = Release|x86
40 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|ARM.ActiveCfg = Debug|ARM
41 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|ARM.Build.0 = Debug|ARM
42 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|ARM.Deploy.0 = Debug|ARM
43 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|x64.ActiveCfg = Debug|x64
44 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|x64.Build.0 = Debug|x64
45 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|x64.Deploy.0 = Debug|x64
46 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|x86.ActiveCfg = Debug|x86
47 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|x86.Build.0 = Debug|x86
48 | {7604B769-C16A-470F-8239-BD83149E972A}.Debug|x86.Deploy.0 = Debug|x86
49 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|ARM.ActiveCfg = Release|ARM
50 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|ARM.Build.0 = Release|ARM
51 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|ARM.Deploy.0 = Release|ARM
52 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|x64.ActiveCfg = Release|x64
53 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|x64.Build.0 = Release|x64
54 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|x64.Deploy.0 = Release|x64
55 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|x86.ActiveCfg = Release|x86
56 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|x86.Build.0 = Release|x86
57 | {7604B769-C16A-470F-8239-BD83149E972A}.Release|x86.Deploy.0 = Release|x86
58 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|ARM.ActiveCfg = Debug|ARM
59 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|ARM.Build.0 = Debug|ARM
60 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|ARM.Deploy.0 = Debug|ARM
61 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|x64.ActiveCfg = Debug|x64
62 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|x64.Build.0 = Debug|x64
63 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|x64.Deploy.0 = Debug|x64
64 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|x86.ActiveCfg = Debug|x86
65 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|x86.Build.0 = Debug|x86
66 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Debug|x86.Deploy.0 = Debug|x86
67 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|ARM.ActiveCfg = Release|ARM
68 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|ARM.Build.0 = Release|ARM
69 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|ARM.Deploy.0 = Release|ARM
70 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|x64.ActiveCfg = Release|x64
71 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|x64.Build.0 = Release|x64
72 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|x64.Deploy.0 = Release|x64
73 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|x86.ActiveCfg = Release|x86
74 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|x86.Build.0 = Release|x86
75 | {6563F4FE-24A3-43EF-AE3F-D53F17929DAF}.Release|x86.Deploy.0 = Release|x86
76 | EndGlobalSection
77 | GlobalSection(SolutionProperties) = preSolution
78 | HideSolutionNode = FALSE
79 | EndGlobalSection
80 | EndGlobal
81 |
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.MessageRelay/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.MessageRelay/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.MessageRelay/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.MessageRelay/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.MessageRelay/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.MessageRelay/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.MessageRelay/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
14 |
15 |
16 |
17 |
18 | UwpMessageRelay.MessageRelay
19 | Lee
20 | Assets\StoreLogo.png
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
40 |
41 |
42 |
43 |
44 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UwpMessageRelay.MessageRelay")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UwpMessageRelay.MessageRelay")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/StartupTask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Windows.ApplicationModel.AppService;
8 | using Windows.ApplicationModel.Background;
9 | using Windows.Foundation.Collections;
10 | using Windows.Storage;
11 |
12 | namespace UwpMessageRelay.MessageRelay
13 | {
14 | public sealed class StartupTask : IBackgroundTask
15 | {
16 | private BackgroundTaskDeferral _backgroundTaskDeferral;
17 | private Guid _thisConnectionGuid;
18 | private static readonly Dictionary Connections = new Dictionary();
19 | private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1);
20 |
21 | ///
22 | /// When an AppServiceConnection of type 'UwpMessageRelayService' (as
23 | /// defined in Package.appxmanifest) is instantiated and OpenAsync() is called
24 | /// on it, then one of these StartupTask's in instantiated and Run() is called.
25 | ///
26 | ///
27 | public async void Run(IBackgroundTaskInstance taskInstance)
28 | {
29 | try
30 | {
31 | // get a service deferral so the service isn't terminated upon completion of Run()
32 | _backgroundTaskDeferral = taskInstance.GetDeferral();
33 | // save a unique identifier for each connection
34 | _thisConnectionGuid = Guid.NewGuid();
35 | var triggerDetails = taskInstance.TriggerDetails as AppServiceTriggerDetails;
36 | var connection = triggerDetails?.AppServiceConnection;
37 | if (connection == null)
38 | {
39 | await Error("AppServiceConnection was null, ignorning this request");
40 | _backgroundTaskDeferral.Complete();
41 | return;
42 | }
43 | // save the guid and connection in a *static* list of all connections
44 | Connections.Add(_thisConnectionGuid, connection);
45 | await Debug("Connection opened: " + _thisConnectionGuid);
46 | taskInstance.Canceled += OnTaskCancelled;
47 | // listen for incoming app service requests
48 | connection.RequestReceived += ConnectionRequestReceived;
49 | connection.ServiceClosed += ConnectionOnServiceClosed;
50 | }
51 | catch (Exception ex)
52 | {
53 | await Error("Error in startup " + ex);
54 | }
55 | }
56 |
57 | ///
58 | /// This happens when an app closes its connection normally.
59 | ///
60 | private async void OnTaskCancelled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
61 | {
62 | await Info("MessageRelay was cancelled, removing " + _thisConnectionGuid + " from the list of active connections.");
63 | RemoveConnection(_thisConnectionGuid);
64 | if (_backgroundTaskDeferral != null)
65 | {
66 | _backgroundTaskDeferral.Complete();
67 | _backgroundTaskDeferral = null;
68 | }
69 | }
70 |
71 | private async void ConnectionOnServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
72 | {
73 | await Debug("Connection closed: " + _thisConnectionGuid);
74 | RemoveConnection(_thisConnectionGuid);
75 | }
76 |
77 | private async Task Error(string message, Exception ex = null)
78 | {
79 | await Write("ERROR", message + " - " + ex);
80 | }
81 |
82 | private async Task Info(string message)
83 | {
84 | await Write("INFO", message);
85 | }
86 |
87 | private async Task Debug(string message)
88 | {
89 | //await Write("DEBUG", message);
90 | }
91 |
92 | ///
93 | /// Writes logs to the LocalFolder. On Windows IoT on a Pi this would be like:
94 | /// '\User Folders\LocalAppData\UwpMessageRelay.MessageRelay-uwp_1.0.0.0_arm__n7wdzm614gaee\LocalState\MessageRelayLogs'
95 | /// On an x86 Windows machine it would be something like:
96 | /// C:\Users\[user]\AppData\Local\Packages\UwpMessageRelay.MessageRelay-uwp_n7wdzm614gaee\LocalState\MessageRelayLogs
97 | ///
98 | private async Task Write(string level, string message)
99 | {
100 | var logFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("MessageRelayLogs",
101 | CreationCollisionOption.OpenIfExists);
102 | var messageRelayLogsPath = Path.Combine(logFolder.Path, "MessageRelayLogs.txt");
103 | var contents = $"{DateTime.Now} - {level} - {message}{Environment.NewLine}";
104 | await Semaphore.WaitAsync();
105 | try
106 | {
107 | File.AppendAllText(messageRelayLogsPath, contents);
108 | }
109 | finally
110 | {
111 | Semaphore.Release(1);
112 | }
113 | }
114 |
115 | private async void ConnectionRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
116 | {
117 | // take out a deferral since we use await
118 | var appServiceDeferral = args.GetDeferral();
119 | try
120 | {
121 | await Debug("Request initiated by " + _thisConnectionGuid);
122 |
123 | // .ToList() required since connections may get removed during SendMessage()
124 | var otherConnections = Connections
125 | .Where(i => i.Key != _thisConnectionGuid)
126 | .ToList();
127 | foreach (var connection in otherConnections)
128 | {
129 | await SendMessage(connection, args.Request.Message);
130 | }
131 | }
132 | finally
133 | {
134 | appServiceDeferral.Complete();
135 | }
136 | }
137 |
138 | private async Task SendMessage(KeyValuePair connection, ValueSet valueSet)
139 | {
140 | try
141 | {
142 | var result = await connection.Value.SendMessageAsync(valueSet);
143 | if (result.Status == AppServiceResponseStatus.Success)
144 | {
145 | await Debug("Successfully sent message to " + connection.Key + ". Result = " + result.Message);
146 | return;
147 | }
148 | if (result.Status == AppServiceResponseStatus.Failure)
149 | {
150 | // When an app with an open connection is terminated and it fails
151 | // to dispose of its connection, the connection object remains
152 | // in Connections. When someone tries to send to it, it gets
153 | // an AppServiceResponseStatus.Failure response
154 | await Info("Error sending to " + connection.Key + ". Removing it from the list of active connections.");
155 | RemoveConnection(connection.Key);
156 | return;
157 | }
158 | await Error("Error sending to " + connection.Key + " - " + result.Status);
159 | }
160 | catch (Exception ex)
161 | {
162 | await Error("Error SendMessage to " + connection.Key + " " + ex);
163 | }
164 | }
165 |
166 | private void RemoveConnection(Guid key)
167 | {
168 | var connection = Connections[key];
169 | connection.Dispose();
170 | Connections.Remove(key);
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/UwpMessageRelay.MessageRelay.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {2e51632e-e824-4a35-b0e0-8757de421c24}
8 | winmdobj
9 | Properties
10 | UwpMessageRelay.MessageRelay
11 | UwpMessageRelay.MessageRelay
12 | en-US
13 | UAP
14 | 10.0.14393.0
15 | 10.0.10586.0
16 | 14
17 | true
18 | 512
19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
20 | false
21 |
22 |
23 | UwpMessageRelay.MessageRelay_TemporaryKey.pfx
24 |
25 | true
26 | true
27 |
28 |
29 |
30 | true
31 | bin\ARM\Debug\
32 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
33 | ;2008
34 | full
35 | ARM
36 | false
37 | prompt
38 | true
39 |
40 |
41 | bin\ARM\Release\
42 | TRACE;NETFX_CORE;WINDOWS_UWP
43 | true
44 | ;2008
45 | pdbonly
46 | ARM
47 | false
48 | prompt
49 | true
50 | true
51 |
52 |
53 | true
54 | bin\x64\Debug\
55 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
56 | ;2008
57 | full
58 | x64
59 | false
60 | prompt
61 | true
62 |
63 |
64 | bin\x64\Release\
65 | TRACE;NETFX_CORE;WINDOWS_UWP
66 | true
67 | ;2008
68 | pdbonly
69 | x64
70 | false
71 | prompt
72 | true
73 | true
74 |
75 |
76 | true
77 | bin\x86\Debug\
78 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
79 | ;2008
80 | full
81 | x86
82 | false
83 | prompt
84 | true
85 |
86 |
87 | bin\x86\Release\
88 | TRACE;NETFX_CORE;WINDOWS_UWP
89 | true
90 | ;2008
91 | pdbonly
92 | x86
93 | false
94 | prompt
95 | true
96 | true
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | Designer
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | false
117 | false
118 | false
119 | false
120 | false
121 | false
122 | false
123 |
124 |
125 | 14.0
126 |
127 |
128 |
135 |
136 |
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/UwpMessageRelay.MessageRelay_TemporaryKey.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.MessageRelay/UwpMessageRelay.MessageRelay_TemporaryKey.pfx
--------------------------------------------------------------------------------
/UwpMessageRelay.MessageRelay/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using Windows.ApplicationModel;
4 | using Windows.ApplicationModel.Activation;
5 | using Windows.UI.Xaml;
6 | using Windows.UI.Xaml.Controls;
7 | using Windows.UI.Xaml.Navigation;
8 | using UwpMessageRelay.Producer.Services;
9 |
10 | namespace UwpMessageRelay.Producer
11 | {
12 | ///
13 | /// Provides application-specific behavior to supplement the default Application class.
14 | ///
15 | sealed partial class App
16 | {
17 | private readonly MessageRelayService _connection = MessageRelayService.Instance;
18 |
19 | ///
20 | /// Initializes the singleton application object. This is the first line of authored code
21 | /// executed, and as such is the logical equivalent of main() or WinMain().
22 | ///
23 | public App()
24 | {
25 | InitializeComponent();
26 | Suspending += OnSuspending;
27 | LeavingBackground += OnLeavingBackground;
28 | }
29 |
30 | private async void OnLeavingBackground(object sender, LeavingBackgroundEventArgs leavingBackgroundEventArgs)
31 | {
32 | try
33 | {
34 | await _connection.Open();
35 | }
36 | catch (Exception ex)
37 | {
38 | // failing quietly is probably ok for now since the connection will
39 | // attempt to re-open itself again on next send. It just means
40 | // we won't be able to receive messages
41 | Debug.WriteLine("Error opening connection on startup" + ex);
42 | }
43 | }
44 |
45 | ///
46 | /// Invoked when the application is launched normally by the end user. Other entry points
47 | /// will be used such as when the application is launched to open a specific file.
48 | ///
49 | /// Details about the launch request and process.
50 | protected override void OnLaunched(LaunchActivatedEventArgs e)
51 | {
52 | #if DEBUG
53 | if (System.Diagnostics.Debugger.IsAttached)
54 | {
55 | DebugSettings.EnableFrameRateCounter = true;
56 | }
57 | #endif
58 | Frame rootFrame = Window.Current.Content as Frame;
59 |
60 | // Do not repeat app initialization when the Window already has content,
61 | // just ensure that the window is active
62 | if (rootFrame == null)
63 | {
64 | // Create a Frame to act as the navigation context and navigate to the first page
65 | rootFrame = new Frame();
66 |
67 | rootFrame.NavigationFailed += OnNavigationFailed;
68 |
69 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
70 | {
71 | //TODO: Load state from previously suspended application
72 | }
73 |
74 | // Place the frame in the current Window
75 | Window.Current.Content = rootFrame;
76 | }
77 |
78 | if (e.PrelaunchActivated == false)
79 | {
80 | if (rootFrame.Content == null)
81 | {
82 | // When the navigation stack isn't restored navigate to the first page,
83 | // configuring the new page by passing required information as a navigation
84 | // parameter
85 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
86 | }
87 | // Ensure the current window is active
88 | Window.Current.Activate();
89 | }
90 | }
91 |
92 | ///
93 | /// Invoked when Navigation to a certain page fails
94 | ///
95 | /// The Frame which failed navigation
96 | /// Details about the navigation failure
97 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
98 | {
99 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
100 | }
101 |
102 | ///
103 | /// Invoked when application execution is being suspended. Application state is saved
104 | /// without knowing whether the application will be terminated or resumed with the contents
105 | /// of memory still intact.
106 | ///
107 | /// The source of the suspend request.
108 | /// Details about the suspend request.
109 | private void OnSuspending(object sender, SuspendingEventArgs e)
110 | {
111 | var deferral = e.SuspendingOperation.GetDeferral();
112 |
113 | _connection.CloseConnection();
114 |
115 | deferral.Complete();
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Producer/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Producer/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Producer/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Producer/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Producer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Producer/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Producer/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Message results
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using Windows.Foundation.Collections;
5 | using Windows.UI.Xaml;
6 | using UwpMessageRelay.Producer.Services;
7 |
8 | namespace UwpMessageRelay.Producer
9 | {
10 | public sealed partial class MainPage
11 | {
12 | private readonly MessageRelayService _connection = MessageRelayService.Instance;
13 |
14 | public MainPage()
15 | {
16 | InitializeComponent();
17 | Loaded += OnLoaded;
18 | _connection.OnMessageReceived += ConnectionOnMessageReceived;
19 | }
20 |
21 | private async void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
22 | {
23 | await EnsureConnected();
24 | }
25 |
26 | private async Task EnsureConnected()
27 | {
28 | var retryDelay = 10000;
29 | await Task.Delay(retryDelay);
30 | while (!_connection.IsConnected)
31 | {
32 | try
33 | {
34 | await _connection.Open();
35 | }
36 | catch (Exception)
37 | {
38 | // note ensure MessageRelay is deployed by right clicking on UwpMessageRelay.MessageRelay and selecting "Deploy"
39 | MessageResults.Text = $"Unable to connect to siren of shame engine. Retrying in {(retryDelay / 1000)} seconds...";
40 | await Task.Delay(retryDelay);
41 | }
42 | }
43 | }
44 |
45 | private async void ConnectionOnMessageReceived(ValueSet valueSet)
46 | {
47 | await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
48 | {
49 | var message = valueSet.First();
50 | MessageResults.Text = $"{message.Value}";
51 | });
52 | }
53 |
54 | private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
55 | {
56 | MessageResults.Text = "Sending Message";
57 | try
58 | {
59 | await _connection.SendMessageAsync("Echo", Message.Text);
60 | MessageResults.Text = "Message Sent Successfully";
61 | }
62 | catch (Exception ex)
63 | {
64 | MessageResults.Text = "Send error: " + ex.Message;
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | UwpMessageRelay.Producer
18 | Lee
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("UwpMessageRelay.Producer")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("UwpMessageRelay.Producer")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/Services/MessageRelayService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 | using Windows.ApplicationModel.AppService;
5 | using Windows.Foundation.Collections;
6 |
7 | namespace UwpMessageRelay.Producer.Services
8 | {
9 | public class MessageRelayService
10 | {
11 | const string AppServiceName = "UwpMessageRelayService";
12 | private AppServiceConnection _connection;
13 | public event Action OnMessageReceived;
14 |
15 | // Todo: convert to dependency injection
16 | public static MessageRelayService Instance { get; } = new MessageRelayService();
17 | public bool IsConnected => _connection != null;
18 |
19 | private async Task CachedConnection()
20 | {
21 | if (_connection != null) return _connection;
22 | _connection = await MakeConnection();
23 | _connection.RequestReceived += ConnectionOnRequestReceived;
24 | _connection.ServiceClosed += ConnectionOnServiceClosed;
25 | return _connection;
26 | }
27 |
28 | public async Task Open()
29 | {
30 | await CachedConnection();
31 | }
32 |
33 | private async Task MakeConnection()
34 | {
35 | var listing = await AppServiceCatalog.FindAppServiceProvidersAsync(AppServiceName);
36 |
37 | if (listing.Count == 0)
38 | {
39 | throw new Exception("Unable to find app service '" + AppServiceName + "'");
40 | }
41 | var packageName = listing[0].PackageFamilyName;
42 |
43 | var connection = new AppServiceConnection
44 | {
45 | AppServiceName = AppServiceName,
46 | PackageFamilyName = packageName
47 | };
48 |
49 | var status = await connection.OpenAsync();
50 |
51 | if (status != AppServiceConnectionStatus.Success)
52 | {
53 | throw new Exception("Could not connect to MessageRelay, status: " + status);
54 | }
55 |
56 | return connection;
57 | }
58 |
59 | private void ConnectionOnServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
60 | {
61 | DisposeConnection();
62 | }
63 |
64 | private void DisposeConnection()
65 | {
66 | if (_connection == null) return;
67 |
68 | _connection.RequestReceived -= ConnectionOnRequestReceived;
69 | _connection.ServiceClosed -= ConnectionOnServiceClosed;
70 | _connection.Dispose();
71 | _connection = null;
72 | }
73 |
74 | private void ConnectionOnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
75 | {
76 | var appServiceDeferral = args.GetDeferral();
77 | try
78 | {
79 | ValueSet valueSet = args.Request.Message;
80 | OnMessageReceived?.Invoke(valueSet);
81 | }
82 | finally
83 | {
84 | appServiceDeferral.Complete();
85 | }
86 | }
87 |
88 | public void CloseConnection()
89 | {
90 | DisposeConnection();
91 | }
92 |
93 | private async Task SendMessageAsync(KeyValuePair keyValuePair)
94 | {
95 | var connection = await CachedConnection();
96 | var result = await connection.SendMessageAsync(new ValueSet { keyValuePair });
97 | if (result.Status == AppServiceResponseStatus.Success)
98 | {
99 | return;
100 | }
101 | throw new Exception("Error sending " + result.Status);
102 | }
103 |
104 | public async Task SendMessageAsync(string key, string value)
105 | {
106 | await SendMessageAsync(new KeyValuePair(key, value));
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/UwpMessageRelay.Producer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {7604B769-C16A-470F-8239-BD83149E972A}
8 | AppContainerExe
9 | Properties
10 | UwpMessageRelay.Producer
11 | UwpMessageRelay.Producer
12 | en-US
13 | UAP
14 | 10.0.14393.0
15 | 10.0.10586.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | UwpMessageRelay.Producer_TemporaryKey.pfx
20 |
21 |
22 | true
23 | bin\x86\Debug\
24 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
25 | ;2008
26 | full
27 | x86
28 | false
29 | prompt
30 | true
31 |
32 |
33 | bin\x86\Release\
34 | TRACE;NETFX_CORE;WINDOWS_UWP
35 | true
36 | ;2008
37 | pdbonly
38 | x86
39 | false
40 | prompt
41 | true
42 | true
43 |
44 |
45 | true
46 | bin\ARM\Debug\
47 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
48 | ;2008
49 | full
50 | ARM
51 | false
52 | prompt
53 | true
54 |
55 |
56 | bin\ARM\Release\
57 | TRACE;NETFX_CORE;WINDOWS_UWP
58 | true
59 | ;2008
60 | pdbonly
61 | ARM
62 | false
63 | prompt
64 | true
65 | true
66 |
67 |
68 | true
69 | bin\x64\Debug\
70 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
71 | ;2008
72 | full
73 | x64
74 | false
75 | prompt
76 | true
77 |
78 |
79 | bin\x64\Release\
80 | TRACE;NETFX_CORE;WINDOWS_UWP
81 | true
82 | ;2008
83 | pdbonly
84 | x64
85 | false
86 | prompt
87 | true
88 | true
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | App.xaml
97 |
98 |
99 | MainPage.xaml
100 |
101 |
102 |
103 |
104 |
105 |
106 | Designer
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | MSBuild:Compile
123 | Designer
124 |
125 |
126 | MSBuild:Compile
127 | Designer
128 |
129 |
130 |
131 | 14.0
132 |
133 |
134 |
141 |
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/UwpMessageRelay.Producer_TemporaryKey.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lprichar/UwpMessageRelay/1aefa2efff55eada8c6acdf7b8876dd658971d52/UwpMessageRelay.Producer/UwpMessageRelay.Producer_TemporaryKey.pfx
--------------------------------------------------------------------------------
/UwpMessageRelay.Producer/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.1.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------