Запуск UWP приложения из другой программы

572
23 декабря 2016, 11:44

Есть UWP приложение, его нужно запустить из другой программы, запуск .exe не удаётся. Как можно корректно реализовать вызов UWP приложения из другого приложения?

Answer 1

Согласно этому ответу нужно иметь идентификатор вызываемого приложения, далее appUserModelId. Ну и запустить приложение с помощью ApplicationActivationManager который надо предварительно импортировать из COM

    public enum ActivateOptions
    {
        None = 0x00000000,  // No flags set
        DesignMode = 0x00000001,  // The application is being activated for design mode, and thus will not be able to
        // to create an immersive window. Window creation must be done by design tools which
        // load the necessary components by communicating with a designer-specified service on
        // the site chain established on the activation manager.  The splash screen normally
        // shown when an application is activated will also not appear.  Most activations
        // will not use this flag.
        NoErrorUI = 0x00000002,  // Do not show an error dialog if the app fails to activate.                                
        NoSplashScreen = 0x00000004,  // Do not show the splash screen when activating the app.
    }

    //Импортируем интерфейс
    [ComImport, Guid("2e941141-7f97-4756-ba1d-9decde894a3d"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IApplicationActivationManager
    {
        // Activates the specified immersive application for the "Launch" contract, passing the provided arguments
        // string into the application.  Callers can obtain the process Id of the application instance fulfilling this contract.
        IntPtr ActivateApplication([In] String appUserModelId, [In] String arguments, [In] ActivateOptions options, [Out] out UInt32 processId);
        IntPtr ActivateForFile([In] String appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] String verb, [Out] out UInt32 processId);
        IntPtr ActivateForProtocol([In] String appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out UInt32 processId);
    }
    //Импортируем реализацию интерфейса
    [ComImport, Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")]//Application Activation Manager
    class ApplicationActivationManager : IApplicationActivationManager
    {
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)/*, PreserveSig*/]
        public extern IntPtr ActivateApplication([In] String appUserModelId, [In] String arguments, [In] ActivateOptions options, [Out] out UInt32 processId);
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        public extern IntPtr ActivateForFile([In] String appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] String verb, [Out] out UInt32 processId);
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        public extern IntPtr ActivateForProtocol([In] String appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out UInt32 processId);
    }

    class Program
    {
        static void Main(string[] args)
        {
            ApplicationActivationManager appActiveManager = new ApplicationActivationManager();//Class not registered
            uint pid;
            appActiveManager.ActivateApplication("2c123c17-8b21-4eb8-8b7f-fdc35c8b7718_n2533ggrncqjt!App", null, ActivateOptions.None, out pid);
            Console.WriteLine();
            Console.ReadLine();
        }
    }

Остается только найти этот самый appUserModelId, согласно тому же ответу из английского SO его можно найти в ветке HKCU

И еще немнго про протокол активации:
https://msdn.microsoft.com/ru-ru/windows/uwp/xbox-apps/automate-launching-uwp-apps

Answer 2

Можно решить проблему при помощи следующего кода на C++

#include "stdafx.h"
#include <ShObjIdl.h>
#include <atlbase.h>
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, nullptr, AO_NONE,
            &pid);
        if (FAILED(hr))
        {
            wprintf(L"LaunchApp %s: Failed to Activate App. hr = 0x%08lx \n", AUMID, hr);
        }
    }
}
CoUninitialize();
return hr;
}

int main()
{
    LPCWSTR id = L"0245c1a2-da90-47fc-baec-c0d81db40d77_nkmqfabk7hsn6!App";
    LaunchApp(id);
    return 0;
}

где LPCWSTR id - это AUMID — имя семейства пакетов с идущими за ним восклицательным знаком и идентификатором приложения.Имя семейства пакетов можно найти в файле Package.appxmanifest вашего UWP приложения.Идентификатор приложения можно найти в том же Package.appxmanifest (открытом в представлении XML) в разделе <Applications>

READ ALSO
Как сделать запрет на закрытие формы?

Как сделать запрет на закрытие формы?

Как сделать запрет на закрытие пользовательской формы?

324
Linq2Xml ограничение на загрузку из XML файла

Linq2Xml ограничение на загрузку из XML файла

Здравствуйте есть большой XML файл, более 500000 записей, из него часто приходится дергать корректировочную информациючтобы не грузить файл...

418
cefsharp не запоминает логин

cefsharp не запоминает логин

Подскажите, как в CefSharp сделать так, что бы при повторном входе появлялось окно с логином (пароль при этом не запоминать)

440