Поделиться через


Расширенная активация с помощью API жизненного цикла приложения

В пакете SDK для приложений Windows API жизненного цикла приложения обеспечивает поддержку расширенной активации в стиле UWP для всех приложений, упакованных и распакованных. В первом выпуске основное внимание уделяется привлечению наиболее часто используемых типов активации к распаковке приложений, а будущие выпуски предназначены для поддержки более 44 типов активации UWP.

Поддержка расширенных активаций требует двух шагов.

  • Сообщите системе, что ваше приложение поддерживает один или несколько расширенных типов активации.
  • Получение и обработка полезных данных активации, получаемых приложением при активации.

Необходимые компоненты

Чтобы использовать API жизненного цикла приложения в пакете SDK для приложений Для Windows:

  1. Скачайте и установите последнюю версию пакета SDK для приложений Windows. Дополнительные сведения см. в статье "Начало работы с WinUI".
  2. Выполните инструкции по созданию простого проекта WinUI 3 или применению пакета SDK для приложений Windows в существующем проекте.

Сведения о активации для распакованных приложений

Текущая версия пакета SDK для приложений Windows поддерживает четыре наиболее распространенных типа активации для распаковки приложений. Эти типы активации определяются перечислением ExtendedActivationKind .

Тип активации Description
Launch Активируйте приложение из командной строки, когда пользователь дважды щелкает значок приложения или программным способом через ShellExecute или CreateProcess.
File Активируйте приложение, зарегистрированное для типа файла, когда файл типа открывается с помощью ShellExecute, Launcher.LaunchFileAsync или командной строки.
Protocol Активируйте приложение, зарегистрированное для протокола, если строка этого протокола выполняется с помощью ShellExecute, Launcher.LaunchUriAsync или командной строки.
StartupTask Активируйте приложение при входе пользователя в Windows из-за раздела реестра или из-за ярлыка в известной папке запуска.

Каждый тип распакованных приложений извлекает свои аргументы командной строки разными способами. Например, приложения C++ Win32 ожидают получения аргументов активации, передаваемых WinMain в виде строки (хотя они также имеют возможность вызывать GetCommandLineW). Однако приложения Windows Forms должны вызывать Environment.GetCommandLineArgs, так как аргументы не будут автоматически передаваться в них.

Сведения о активации упакованных приложений

Упакованные приложения, использующие пакет SDK приложений Windows, поддерживают все 44 типа активации UWP. Каждый тип активации имеет собственную соответствующую реализацию IActivatedEventArgs , которая содержит свойства, относящиеся к этому конкретному типу активации.

Упакованные приложения всегда получают аргументы событий активации в обработчике событий AppInstance.Activated , а также могут вызывать AppInstance.GetActivatedEventArgs.

Регистрация активации

Все приложения поддерживают Launch тип активации по умолчанию. В отличие от UWP, тип активации пакета SDK для Launch Windows включает запуски командной строки. Приложения могут регистрироваться для дополнительных типов активации несколькими способами.

  • Распакованные приложения, использующие пакет SDK для приложений Windows, могут зарегистрировать (и отменить регистрацию) для дополнительных типов активации с помощью API жизненного цикла приложений в пакете SDK для приложений Windows.
  • Распакованные приложения могут продолжать регистрироваться для дополнительных типов активации с помощью традиционного метода написания разделов реестра.
  • Упакованные приложения могут регистрироваться для дополнительных типов активации с помощью записей в манифесте приложения.

Регистрация активации — это пользователь. Если приложение установлено для нескольких пользователей, необходимо повторно зарегистрировать активации для каждого пользователя.

Примеры

Регистрация для расширенной активации

Хотя приложения могут вызывать API регистрации в любое время, наиболее распространенный сценарий — проверка регистрации при запуске приложения.

В этом примере показано, как распаковка приложения может использовать следующие статические методы класса ActivationRegistrationManager для регистрации для нескольких типов активации при запуске приложения:

В этом примере также показано, как использовать функции MddBootstrapInitialize и MddBootstrapShutdown для инициализации и очистки ссылок на пакет пакета SDK для приложений Windows. Все распакованные приложения должны сделать это, чтобы использовать API, предоставляемые пакетом SDK для приложений Windows. Дополнительные сведения см. в разделе "Использование среды выполнения пакета SDK для приложений Windows", упакованных с внешним расположением или распаковкой.

Примечание.

В этом примере регистрируются связи с тремя типами файлов изображений одновременно. Это удобно, но результат совпадает с регистрацией каждого типа файла по отдельности; Регистрация новых типов изображений не перезаписывает предыдущие регистрации. Однако если приложение повторно регистрирует уже зарегистрированный тип файла с другим набором команд, предыдущий набор команд будет перезаписан для этого типа файла.

const UINT32 majorMinorVersion{ WINDOWSAPPSDK_RELEASE_MAJORMINOR };
PCWSTR versionTag{ WINDOWSAPPSDK_RELEASE_VERSION_TAG_W };
const PACKAGE_VERSION minVersion{ WINDOWSAPPSDK_RUNTIME_VERSION_UINT64 };
WCHAR szExePath[MAX_PATH]{};
WCHAR szExePathAndIconIndex[MAX_PATH + 8]{};

int APIENTRY wWinMain(
    _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // Initialize Windows App SDK framework package for unpackaged apps.
    HRESULT hr{ MddBootstrapInitialize(majorMinorVersion, versionTag, minVersion) };
    if (FAILED(hr))
    {
        wprintf(L"Error 0x%X in MddBootstrapInitialize(0x%08X, %s, %hu.%hu.%hu.%hu)\n",
            hr, majorMinorVersion, versionTag, minVersion.Major, 
            minVersion.Minor, minVersion.Build, minVersion.Revision);
        return hr;
    }

    // Get the current executable filesystem path, so we can
    // use it later in registering for activation kinds.
    GetModuleFileName(NULL, szExePath, MAX_PATH);
    wcscpy_s(szExePathAndIconIndex, szExePath);
    wcscat_s(szExePathAndIconIndex, L",1");

    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_CLASSNAME, szWindowClass, MAX_LOADSTRING);
    RegisterWindowClass(hInstance);
    if (!InitInstance(hInstance, nCmdShow))
    {
        return FALSE;
    }

    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // Uninitialize Windows App SDK.
    MddBootstrapShutdown();
    return (int)msg.wParam;
}

void RegisterForActivation()
{
    OutputMessage(L"Registering for rich activation");

    // Register one or more supported filetypes, specifying 
    // an icon (specified by binary file path plus resource index),
    // a display name to use in Shell and Settings,
    // zero or more verbs for the File Explorer context menu,
    // and the path to the EXE to register for activation.
    hstring myFileTypes[3] = { L".foo", L".foo2", L".foo3" };
    hstring verbs[2] = { L"view", L"edit" };
    ActivationRegistrationManager::RegisterForFileTypeActivation(
        myFileTypes,
        szExePathAndIconIndex,
        L"Contoso File Types",
        verbs,
        szExePath
    );

    // Register a URI scheme for protocol activation,
    // specifying the scheme name, icon, display name and EXE path.
    ActivationRegistrationManager::RegisterForProtocolActivation(
        L"foo",
        szExePathAndIconIndex,
        L"Contoso Foo Protocol",
        szExePath
    );

    // Register for startup activation.
    // As we're registering for startup activation multiple times,
    // and this is a multi-instance app, we'll get multiple instances
    // activated at startup.
    ActivationRegistrationManager::RegisterForStartupActivation(
        L"ContosoStartupId",
        szExePath
    );

    // If we don't specify the EXE, it will default to this EXE.
    ActivationRegistrationManager::RegisterForStartupActivation(
        L"ContosoStartupId2",
        L""
    );
}

Получение расширенных аргументов события активации

После активации приложение должно получить свои аргументы события активации. В этом примере распакованное приложение вызывает метод AppInstance.GetActivatedEventArgs , чтобы получить аргументы события для события активации, а затем использует свойство AppActivationArguments.Kind для получения связей событий для различных типов активаций.

Примечание.

Приложения Win32 обычно получают аргументы командной строки очень рано.WinMain Аналогичным образом эти приложения должны вызывать AppInstance.GetActivatedEventArgs в том же месте, где ранее они использовали предоставленный lpCmdLine параметр или вызвали.GetCommandLineW

void GetActivationInfo()
{
    AppActivationArguments args = AppInstance::GetCurrent().GetActivatedEventArgs();
    ExtendedActivationKind kind = args.Kind();
    if (kind == ExtendedActivationKind::Launch)
    {
        ILaunchActivatedEventArgs launchArgs = 
            args.Data().as<ILaunchActivatedEventArgs>();
        if (launchArgs != NULL)
        {
            winrt::hstring argString = launchArgs.Arguments().c_str();
            std::vector<std::wstring> argStrings = split_strings(argString);
            OutputMessage(L"Launch activation");
            for (std::wstring s : argStrings)
            {
                OutputMessage(s.c_str());
            }
        }
    }
    else if (kind == ExtendedActivationKind::File)
    {
        IFileActivatedEventArgs fileArgs = 
            args.Data().as<IFileActivatedEventArgs>();
        if (fileArgs != NULL)
        {
            IStorageItem file = fileArgs.Files().GetAt(0);
            OutputFormattedMessage(
                L"File activation: %s", file.Name().c_str());
        }
    }
    else if (kind == ExtendedActivationKind::Protocol)
    {
        IProtocolActivatedEventArgs protocolArgs = 
            args.Data().as<IProtocolActivatedEventArgs>();
        if (protocolArgs != NULL)
        {
            Uri uri = protocolArgs.Uri();
            OutputFormattedMessage(
                L"Protocol activation: %s", uri.RawUri().c_str());
        }
    }
    else if (kind == ExtendedActivationKind::StartupTask)
    {
        IStartupTaskActivatedEventArgs startupArgs = 
            args.Data().as<IStartupTaskActivatedEventArgs>();
        if (startupArgs != NULL)
        {
            OutputFormattedMessage(
                L"Startup activation: %s", startupArgs.TaskId().c_str());
        }
    }
}

Unregister;

В этом примере показано, как непакованное приложение может динамически отменить регистрацию для определенных типов активации с помощью следующих статических методов класса ActivationRegistrationManager :

Примечание.

При отмене регистрации для активации запуска приложение должно использовать тот же идентификатор задачи, который использовался при первоначальной регистрации.

void UnregisterForActivation()
{
    OutputMessage(L"Unregistering for rich activation");
    
    // Unregister one or more registered filetypes.
    try
    {
        hstring myFileTypes[3] = { L".foo", L".foo2", L".foo3" };
        ActivationRegistrationManager::UnregisterForFileTypeActivation(
            myFileTypes,
            szExePath
        );
    }
    catch (...)
    {
        OutputMessage(L"Error unregistering file types");
    }

    // Unregister a protocol scheme.
    ActivationRegistrationManager::UnregisterForProtocolActivation(
        L"foo",
        L"");

    // Unregister for startup activation.
    ActivationRegistrationManager::UnregisterForStartupActivation(
        L"ContosoStartupId");
    ActivationRegistrationManager::UnregisterForStartupActivation(
        L"ContosoStartupId2");
}