Calling an App Service from a WPF/WinForms Win32 App

I just put up a new sample at https://github.com/arunjeetsingh/SampleCode/tree/master/Win32AppServiceClient. My apologies to all the folks who have been waiting for this sample. I know I promised I’d put up this sample during my Build talk. Well, here it is now. Better late than never right! Who uses this feature? Well, the brand new Outlook 2016 desktop app uses it to talk to Cortana so you’re in good company. Before I dive any deeper into the sample I do want to point out a couple of important limitations of app services when they are called from a Win32 process:

  1. The calling app must be running as the currently logged on user.
  2. When the calling app is a Win32 app the app service background task can not run longer than 30 seconds.

The sample demonstrates a Windows Presentation Foundation (WPF) app calling a universal app service. App services are a new feature of universal Windows 10 apps that allow an app to provide services to other apps. These services can be accessed by other apps as well as Win32 apps such as WPF or WinForms apps.

This sample demonstrates how a WPF app can call into an app service. To run the sample you will need Visual Studio 2015 and the Windows SDK. Both of these can be found at http://developer.windows.com.

With Visual Studio, open the solution Win32AppServiceClient.sln. There are three projects in this solution:

  • RandomNumberService – This project is a Windows Runtime component. It contains the code for the background task that implements the app service we use for the sample. RandomNumberGeneratorTask.cs contains the background task class. The background tasks’ main entrypoint is the Run method. In this method, the RandomNumberGeneratorTask sets itself up with a deferral so it can stay running and provide the app service. It also uses the incoming AppServiceTriggerDetails to attach an event handler to the AppServiceTriggerDetails.RequestReceived event. This enables the RandomNumberGeneratprTask to respond to requests from the app service client. The OnRequestReceived handler simply parses the input for minimum and maximum integer values. It then generates a random number between those values and returns it.
  • AppServicesProvider – AppServicesProvider is the universal Windows app that contains RandomNumberService. The AppServicesProvider project contains a reference to RandomNumberService. The Package.appxmanifest file in AppServicesProvider also contains a windows.appService extension. This is how the AppServicesProvider app exposes the RandomNumberService to other apps. In the Package.appxmanifest’s uap:Extension element the EntryPoint attribute represents the type name of the background task providing the app service. The Name attribute in the uap:AppService element represents the name of the app service.
  • Win32AppServiceClient – The Win32AppServicesClient is a WPF application. The project file of this WPF application (Win32AppServiceClient.csproj) has been modified to include references to the universal Windows 10 APIs. This enables us to use the Windows.ApplicationModel.AppService.AppServiceConnection class that lets an app connect to an app service. The MainWindow.xaml page of Win32AppServiceClient does exactly that. It presents the user the option to provide minimum and maximum integer values. The Click handler of the Generate Random Number button then calls the random number service exposed by AppServicesProvider with these values. The result is then displayed on screen.

Feel free to submit pull requests on this README.md or the code if you think it could use improvement. Happy hacking!

@aruntalkstech

8 thoughts on “Calling an App Service from a WPF/WinForms Win32 App

    1. You mean one that is hosted inside a Win32 app? No. App services rely on the idea of background tasks and a strong identifier (PackageFamilyName) that we can use to identify the owner of the app service. Win32 apps have neither.

      For enterprise scenarios, Brokered Runtime Components are an option: https://msdn.microsoft.com/en-us/library/windows/apps/dn630195.aspx?f=255&MSPPError=-2147217396. Although they have a limitation that your universal app must be side-loaded, not deployed from the store.

      Finally, if you absolutely must have this right now one slightly hacky approach would be to launch the Win32 app using a custom scheme (Launcher.LaunchUriAsync) and then have it connect back to the universal side using an app service.

      With the upcoming Project Centennial https://channel9.msdn.com/events/Build/2015/2-692 this might become easier than it is right now. Centennial apps will have a package family name and also will be able to host background tasks.

      I hope this information helps.

      Like

  1. Hi @aruntalkstech
    Thank you for the article. It’s really helpful. If you don’t mind. I would like to ask the following. Is there anyway to have a Windows Service calling the App Service? The Windows Service would be running as LocalSystem. I tried to impersonate the current user logged in before making the calls but I keep getting the error (status) AppNotInstalled.
    Thank you in advance
    Steven

    Like

    1. Hi Steven. Unfortunately there’s no way to call an app service from a process that isn’t running as the current user (which is the case here). This is very much by design at the moment. One technique I’ve seen others use is to launch another process as the current user (using impersonation) and then have that process talk to the app service on behalf of the Windows service. It isn’t great but it’s the only option.

      Like

      1. Hi @aruntalkstech
        Thank you for the reply. The approach you described is exactly the one that I started exploring.

        Thank you once again

        Like

  2. Hi @aruntalkstech
    If I may bother you again. I’m able to make the win32 app to consume the AppService. But the moment my win32 application is running as administrator that communication doesn’t work. the OpenAsync() returns AppServiceUnavailable. Is this a bug? Are you aware of any workaround?
    Thank you in advance

    Like

    1. Sorry it took me so long to reply Steven. App services only work when the user context of the caller and the callee are the same. This is by design to avoid potential security issues.

      Like

  3. Great post really helpful. I have a situation where I want a published UWP application that uses a WPF executable and entry point Windows.FullTrustApplication. This launches fine. What I then need to do is communicate back to the UWP App Service that originally launched the WPF to perform UWP specific functions that are not supported in WPF land (continental app). Is this possible as a Windows Store application? Some functions I need to present in WPF but other functions I need to perform in UWP but I dont want a UWP window appearing. Just a desktop style app.

    Like

Leave a comment