locked
[UWP] Unable to connect to App service from an noninteractive elevated win32 process RRS feed

  • Question

  • I have 2 apps,the first is a win32 app and the second is an uap.

    A win32 app works with elevated privileges by necessity and should be able to transfer some data to an uap.

    To do this i have a third app, that works like a bridge between win32 and uwp (let's name it the dispatcher app). It is a desktop .NET app, that is started from a win32 app.

    It communicates with a win32 app through the windows messages on one side, and launches an uap and should communicate with it through an app service provided by an uap on another.

    As the dispatcher app is not invoked by user but by win32 app's process, it cannot connect to an app service provided by an uap. Meanwhile it connects to it if user have started it himself.

    Have to say, I know about the capability to launch an uap with parameters. It's not suitable in my scenario. Moreover the dispatcher app should be noninteractive (and it is so) in ideal.

    Also i've tried the way with the Desktop Bridge to add a .NET app (the part of the dispatcher that communicates with uap's app service) to the uap. 

    I've implemented a protocol activation that started this .NET app as a full trust application.

    I've tried to launch an uap through this protocol activation. It started and even could recieve windows messages, but could not connect to an app service with a result AppServiceConnectionStatus.AppServiceUnavailable.

    And thats the questions.

    Is this behaviour by design?

    Is there any workaround to communicate with uap's app service from such an app (noninteractive process)?

    Friday, December 23, 2016 3:49 PM

Answers

  • Hi AlexeySubbotin,

    I do understand your issue since I have already tested the same approaches such as Alias as you did. But it doesn’t make sense. Then I test with launch activation instead of protocol activation and it works noninteractively with the prelaunch option. A prelaunched app is put into background without showing the UI.
    https://msdn.microsoft.com/en-us/windows/uwp/xbox-apps/automate-launching-uwp-apps
    https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/handle-app-prelaunch
    Please refer to the following steps:
    1. Create a Win32 console app and set its target platform version to 10.0.10240.0 or above.
    2. Copy and paste the C++ code (LaunchApp function) which is shown in the previous document.
    3. Change arguments parameter in ActivateApplication method from nullptr to something else.
    4. Change options parameter in ActivateApplication method from AO_NONE to AO_PRELAUNCH which is supported starting in Windows 10.
    5. Call LaunchApp with the AUMID of the UWP app. 
    “The AUMID is the package family name followed by an exclamation point and the application ID.”
    6. The final code in ConsoleApplication1.cpp  is like this.

    // ConsoleApplication1.cpp : Defines the entry point for the console application.
    
    #include "stdafx.h"
    #include <ShObjIdl.h>
    #include <atlbase.h>
    
    HRESULT LaunchApp(LPCWSTR);
    
    int main()
    {
    	LaunchApp(L"Microsoft.AppServiceBridge_8wekyb3d8bbwe!App");
        return 0;
    }
    
    HRESULT LaunchApp(LPCWSTR AUMID)
    {
    	HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
    	if (FAILED(hr))
    	{
    		wprintf(L"LaunchApp %s: Failed to init COM. hr = 0x%08lx \n", AUMID, hr);
    	}
    	{
    		CComPtr<IApplicationActivationManager> AppActivationMgr = nullptr;
    		if (SUCCEEDED(hr))
    		{
    			hr = CoCreateInstance(CLSID_ApplicationActivationManager, nullptr,
    				CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&AppActivationMgr));
    			if (FAILED(hr))
    			{
    				wprintf(L"LaunchApp %s: Failed to create Application Activation Manager.hr = 0x%08lx \n", AUMID, hr);
    			}
    		}
    		if (SUCCEEDED(hr))
    		{
    			DWORD pid = 0;
    			hr = AppActivationMgr->ActivateApplication(AUMID, L"runFullTrust", AO_PRELAUNCH, &pid);
    			if (FAILED(hr))
    			{
    				wprintf(L"LaunchApp %s: Failed to Activate App. hr = 0x%08lx \n", AUMID, hr);
    			}
    		}
    	}
    	CoUninitialize();
    	return hr;
    }
    

    7. In UWP app, add the following code into the OnLaunched override in App.xaml.cs. (don’t forget to uncomment windows.fullTrustProcess Category)

    if(e.PrelaunchActivated && e.Arguments == "runFullTrust")
            await Windows.ApplicationModel.FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
    8. In BackgroundProcess app, add Connect() method into the constructor in WindowsMessagesHandler.cs.
    9. Rebuild the solution, deploy the UWP app, run the ConsoleApplication1.exe as administrator and you will see the success message.

    Best Regards,
    David



      

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by AlexeySubbotin Thursday, December 29, 2016 1:28 PM
    Wednesday, December 28, 2016 8:55 PM

All replies

  • Hi AlexeySubbotin,

    So you have a win32 app and use protocol activation to launch a UWP app. Then in the UWP app, you use full trust to launch a desktop .Net app which is packaged into the UWP app. Finally you use this desktop app as a bridge to communicate with the UWP app (by app service) and the win32 app (by windows message). Am I right?
    I thought you’d better provide some code within your question to make it more clearly. 
    Have you declared the app service and fullTrust capability in the UWP app like the following code snippet if you are using in-process app service?

      <Extensions>
            <uap:Extension Category="windows.appService">
              <uap:AppService Name="CommunicationService" />
            </uap:Extension>
            <desktop:Extension Category="windows.fullTrustProcess" Executable="BackgroundProcess.exe" />
      </Extensions>
      <Capabilities>
            <rescap:Capability Name="runFullTrust" />
      </Capabilities>
      protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
      {
                base.OnBackgroundActivated(args);
                if (args.TaskInstance.TriggerDetails is AppServiceTriggerDetails)
                {
                    appServiceDeferral = args.TaskInstance.GetDeferral();
                    args.TaskInstance.Canceled += OnTaskCanceled; // Associate a cancellation handler with the background task.
    
                    AppServiceTriggerDetails details = args.TaskInstance.TriggerDetails as AppServiceTriggerDetails;
                    Connection = details.AppServiceConnection;
                }
      }

    Are you using the following API to launch the desktop .Net app?

      await Windows.ApplicationModel.FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
    For more information, please refer to the official AppServiceBridgeSample.
    https://github.com/Microsoft/DesktopBridgeToUWP-Samples/tree/master/Samples/AppServiceBridgeSample  

    Best Regards,
    David



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, December 26, 2016 5:34 PM
  • Hi David!

    Yes, i have a win32 app and use protocol activation to launch a UWP app and i use it as a bridge to communicate with the UWP app (by app service) and the win32 app (by windows messages).

    I used the official AppServiceBridgeSample as a base.

    But i have declared a protocol activation with definitions of an executable and an entry point. So if i launch a UWP app through protocol activation, only a desktop .Net app executed without creating a UWP app interface (no windows, no calls to the OnActivated handler).

    <Extensions>
            <uap:Extension Category="windows.protocol" Executable="BackgroundProcess.exe" EntryPoint="Windows.FullTrustApplication">
              <uap:Protocol Name="test.win32.protocol">
                <uap:DisplayName>TestWin32</uap:DisplayName>
              </uap:Protocol>
            </uap:Extension>
            <uap:Extension Category="windows.appService">
              <uap:AppService Name="CommunicationService" />
            </uap:Extension>
    </Extensions>

    The UWP app has the declared "runFullTrust" capability.

    <Capabilities>
        <Capability Name="internetClient" />
        <rescap:Capability Name="runFullTrust" />
    </Capabilities>

    Finally the UWP app is launched through a protocol activation.

    var launcherOptions = new LauncherOptions() { TargetApplicationPackageFamilyName = "Microsoft.AppServiceBridge_8wekyb3d8bbwe" };
    await Launcher.LaunchUriAsync(new Uri("test.win32.protocol:"), launcherOptions);

    And, as i assumed, the launched .Net desktop app should have standard privileges and be capable to connect to an app service of the UWP app.

    If i have executed the win32 app manually through the explorer or from another not elevated process, the .Net desktop app is launched and connects to the app service.

    But if i have executed the win32 app from another app with elevated privileges, the .Net desktop app is launched, but does not connect to the app service with AppServiceConnectionStatus.AppServiceUnavailable as a result.

    I have uploaded a sample solution.

    It contains 4 projects:

    1. BackgroundProcess - the .Net desktop app for using within the UWP with WinRT APIs support, handles windows messages, tries to connect the UWP's app service
    2. UWP - the UWP app itself with declared extensions, capabilities, app service and  BackgroundProcess' executable
    3. TestLauncher - the .Net desktop app with WinRT APIs suppport, launches the BackgroundProcess using protocol activation, sends it 4 bytes using windows messages
    4. TestAppServiceBridge - generally substitutes a win32 app of described scenario, executes the TestLauncher.

    How to use:

    1. Rebuild all, deploy the UWP app and execute TestAppServiceBridge
    2. Click the "Start Test" button (the TestLauncher app should be executed)
    3. In the TestLauncher's main window click the "Launch .Net app" button and the "Send 4 bytes" button (the BackgroundProcess should be executed and 2 messages should be shown ("Recieved: 4 bytes" - confirmation of the recieved windows message, "Connection established - waiting for requests" - confirmation that connection to app service succeeded)
    4. Open the output folder of the TestAppServiceBridge project (AppServiceBridgeSample\cs\TestAppServiceBridge\bin\Release), execute the app (TestAppServiceBridge.exe) with administrator (elevated) privileges
    5. Repeat steps 2-3. The second BackgroundProcess' message should be "The app AppServicesProvider is installed but it does not provide the app service CommunicationService" as a result of failed connection (AppServiceConnectionStatus.AppServiceUnavailable)

    Tuesday, December 27, 2016 11:36 AM
  • Hi AlexeySubbotin,

    I thought the entry point of Windows.FullTrustApplication does not mean that the executable will run in full trust process. As far as I know, the way to launch a full trust process is using the FullTrustProcessLauncher API as mentioned above. I have downloaded your solution, added this API into OnActivated handler and uncomment the windows.fullTrustProcess extension while removing the Executable in protocol. Then it works well. 

    Best Regards,
    David

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by David_FF Tuesday, December 27, 2016 3:26 PM
    Tuesday, December 27, 2016 3:18 PM
  • Hi David,

    I know about a capability to run process as full trust using FullTrustProcessLauncher. And you could notice that i've implemented it in the sample  code. And i've tested it. The .Net app could connect to the app service of the UWP app indeed. But the execution of the UWP app through protocol activation causes the creation of UWP app's window. It's not suitable for my scenario. I do not need to start the UWP app itself at that time. 

    As i assume, if i've launched the executable using the declared entry point of Windows.FullTrustApplication, the executable launches in full trust mode, and it should be able to communicate with the UWP app's app service. In general such approach can be considered as an attempt of the execution of 2 different apps (the converted .Net desktop app and the UWP app with the implemented app service) from one AppX package.

    I'm sure, that there is no differences between the execution of this 2 apps from one AppX package or from two (if i would created 2 different AppX packages for the converted .Net desktop app and the UWP app). The .Net desktop app would not be able to connect to the app service, because it's process is created with elevated priveleges inherited from the process which has launched it. So a full trust application is not full trust at that moment.

    Ok, even if i cannot to use such launch of a full trust application using protocol activation, i've tried to declare an app execution alias in according to the documentation.

    I've modified the UWP app's package manifest file and added an app execution alias

    <?xml version="1.0" encoding="utf-8"?>
    <Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" IgnorableNamespaces="uap mp rescap desktop uap3">
      <Identity Name="Microsoft.AppServiceBridge" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="1.0.0.0" />
      <mp:PhoneIdentity PhoneProductId="1aa93327-07b6-485f-bc70-70cbd5a9ca0a" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
      <Properties>
        <DisplayName>Desktop Bridge AppService Sample</DisplayName>
        <PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
        <Logo>Assets\StoreLogo.png</Logo>
      </Properties>
      <Dependencies>
        <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14332.0" MaxVersionTested="10.0.14332.0" />
      </Dependencies>
      <Resources>
        <Resource Language="x-generate" />
      </Resources>
      <Applications>
        <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="UWP.App">
          <uap:VisualElements DisplayName="Desktop Bridge AppService Sample" Square150x150Logo="Assets\squareTile-sdk.png" Square44x44Logo="Assets\SmallTile-sdk.png" Description="Desktop Bridge AppService Sample" BackgroundColor="#00b2f0">
            <uap:SplashScreen Image="Assets\Splash-sdk.png" />
            <uap:DefaultTile>
              <uap:ShowNameOnTiles>
                <uap:ShowOn Tile="square150x150Logo" />
              </uap:ShowNameOnTiles>
            </uap:DefaultTile>
          </uap:VisualElements>
          <Extensions>
            <uap:Extension Category="windows.appService">
              <uap:AppService Name="CommunicationService" />
            </uap:Extension>
            <uap3:Extension Category="windows.appExecutionAlias" Executable="BackgroundProcess.exe" EntryPoint="Windows.FullTrustApplication">
              <uap3:AppExecutionAlias>
                <desktop:ExecutionAlias Alias="UWPBackgroundProcess.exe" />
              </uap3:AppExecutionAlias>
            </uap3:Extension>
            <desktop:Extension Category="windows.fullTrustProcess" Executable="BackgroundProcess.exe"/>
          </Extensions>
        </Application>
      </Applications>
      <Capabilities>
        <Capability Name="internetClient" />
        <rescap:Capability Name="runFullTrust" />
      </Capabilities>
    </Package>

    And i've modified the button_click method in the MainWindow.xaml.cs in the TestLauncher project to realize the launch of the .Net desktop app using the app execution alias implemented in the UWP app

    private async void button_Click(object sender, RoutedEventArgs e)
    {
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.FileName = "UWPBackgroundProcess";
        Process.Start(startInfo);
    }

    I've tested modified apps in the same way as originals (same steps), and the result was the same. Executed from the process with elevated priveleges the full trust application can not connect to the app service of the UWP app.

    I have to say, that i started to find different approaches to connect to an app service with a full trust process or application, when i was failed to make it from the .Net desktop app with UWP support (as if the TestLauncher app itself had implementation to establishing the connection to the app service and the BackgroundProcess app did not exist) launched with elevated priveleges according to my scenario.

    I hope, it clarifies my issue.



    Wednesday, December 28, 2016 9:05 AM
  • Hi AlexeySubbotin,

    I do understand your issue since I have already tested the same approaches such as Alias as you did. But it doesn’t make sense. Then I test with launch activation instead of protocol activation and it works noninteractively with the prelaunch option. A prelaunched app is put into background without showing the UI.
    https://msdn.microsoft.com/en-us/windows/uwp/xbox-apps/automate-launching-uwp-apps
    https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/handle-app-prelaunch
    Please refer to the following steps:
    1. Create a Win32 console app and set its target platform version to 10.0.10240.0 or above.
    2. Copy and paste the C++ code (LaunchApp function) which is shown in the previous document.
    3. Change arguments parameter in ActivateApplication method from nullptr to something else.
    4. Change options parameter in ActivateApplication method from AO_NONE to AO_PRELAUNCH which is supported starting in Windows 10.
    5. Call LaunchApp with the AUMID of the UWP app. 
    “The AUMID is the package family name followed by an exclamation point and the application ID.”
    6. The final code in ConsoleApplication1.cpp  is like this.

    // ConsoleApplication1.cpp : Defines the entry point for the console application.
    
    #include "stdafx.h"
    #include <ShObjIdl.h>
    #include <atlbase.h>
    
    HRESULT LaunchApp(LPCWSTR);
    
    int main()
    {
    	LaunchApp(L"Microsoft.AppServiceBridge_8wekyb3d8bbwe!App");
        return 0;
    }
    
    HRESULT LaunchApp(LPCWSTR AUMID)
    {
    	HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
    	if (FAILED(hr))
    	{
    		wprintf(L"LaunchApp %s: Failed to init COM. hr = 0x%08lx \n", AUMID, hr);
    	}
    	{
    		CComPtr<IApplicationActivationManager> AppActivationMgr = nullptr;
    		if (SUCCEEDED(hr))
    		{
    			hr = CoCreateInstance(CLSID_ApplicationActivationManager, nullptr,
    				CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&AppActivationMgr));
    			if (FAILED(hr))
    			{
    				wprintf(L"LaunchApp %s: Failed to create Application Activation Manager.hr = 0x%08lx \n", AUMID, hr);
    			}
    		}
    		if (SUCCEEDED(hr))
    		{
    			DWORD pid = 0;
    			hr = AppActivationMgr->ActivateApplication(AUMID, L"runFullTrust", AO_PRELAUNCH, &pid);
    			if (FAILED(hr))
    			{
    				wprintf(L"LaunchApp %s: Failed to Activate App. hr = 0x%08lx \n", AUMID, hr);
    			}
    		}
    	}
    	CoUninitialize();
    	return hr;
    }
    

    7. In UWP app, add the following code into the OnLaunched override in App.xaml.cs. (don’t forget to uncomment windows.fullTrustProcess Category)

    if(e.PrelaunchActivated && e.Arguments == "runFullTrust")
            await Windows.ApplicationModel.FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
    8. In BackgroundProcess app, add Connect() method into the constructor in WindowsMessagesHandler.cs.
    9. Rebuild the solution, deploy the UWP app, run the ConsoleApplication1.exe as administrator and you will see the success message.

    Best Regards,
    David



      

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by AlexeySubbotin Thursday, December 29, 2016 1:28 PM
    Wednesday, December 28, 2016 8:55 PM
  • Hi David,

    It works indeed. Thanks alot for your help!

    Meanwhile, IMHO, the implementation of API for the full trust application launch is incomplete and not clear enough, as it loses all of advantage when desktop application used in a UWP app in similar scenarios is unable to use IPC within single application's package.

    If it was assumed that desktop application should be used only internally, then it's not clear for me why it is available to implement an app execution alias or a protocol activation for a full trust .Net desktop application launch within a UWP app.


    Thursday, December 29, 2016 1:27 PM