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


Перенос функций управления жизненным циклом приложения

В этом разделе содержатся рекомендации по миграции в области жизненного цикла приложения.

Важные API

Сводка различий между API и (или) функциями

приложения универсальная платформа Windows (UWP) по умолчанию являются одноэлементными; По умолчанию приложения пакета SDK для приложений Windows (WinUI 3) являются несколькими экземплярами.

Приложение UWP имеет такие методы приложения, как OnFileActivated, OnSearchActivated, OnActivated и OnBackgroundActivated, которые неявно сообщают о том, как было активировано приложение; В приложении пакета SDK для приложений Для Windows в App.OnLaunched (или в любом методе) вызовите метод (AppInstance.GetActivatedEventArgs), чтобы получить активированные события args и проверить их, чтобы определить, как было активировано приложение.

Также см . строку фоновых задач в таблице в разделе "Что поддерживается при миграции с UWP на WinUI 3 ".

Одноэлементные приложения

приложения универсальная платформа Windows (UWP) по умолчанию являются одно экземплярами (вы можете выбрать поддержку нескольких экземпляров— см. статью "Создание приложения UWP с несколькими экземплярами").

Таким образом, способ поведения одно экземпляра приложения UWP заключается в том, что время запуска второго (и последующего) экземпляра активируется. Предположим, что в приложении UWP вы реализовали функцию сопоставления типов файлов. Если из проводник открыть файл (типа, для которого приложение зарегистрировало сопоставление типов файлов) и приложение уже запущено, то активируется уже запущенный экземпляр.

С другой стороны, приложения пакета SDK для приложений Windows (WinUI 3) по умолчанию используются для нескольких экземпляров. Таким образом, по умолчанию запускается второе (и последующее) время запуска приложения пакета SDK для приложений Windows (WinUI 3), запускается новый экземпляр приложения. Если например приложение пакета SDK для приложений Windows (WinUI 3) реализует сопоставление типов файлов и из проводник открываете файл (правильного типа) во время работы этого приложения, то по умолчанию запускается новый экземпляр приложения.

Если вы хотите, чтобы приложение пакета SDK для приложений Windows (WinUI 3) было одно экземпляром, например приложение UWP, можно переопределить поведение по умолчанию, описанное выше. Вы будете использовать AppInstance.FindOrRegisterForKey и AppInstance.IsCurrent , чтобы определить, является ли текущий экземпляр основным экземпляром. Если это не так, то вызовите AppInstance.RedirectActivationToAsync для перенаправления активации в уже запущенный основной экземпляр, а затем выйти из текущего экземпляра (без создания и активации его главного окна).

Дополнительные сведения см. в разделе "Подключение приложений" с помощью API жизненного цикла приложения.

Внимание

Приведенный ниже код работает должным образом, если вы нацелены на архитектуру x64 . Это относится как к C#, так и к C++/WinRT.

Одноустановка в Main или wWinMain

Лучше всего проверить необходимость перенаправления активации как можно раньше в выполнении приложения. По этой причине рекомендуется выполнить логику одноинстантирования в функции Main приложения (или wWinMain для C++/WinRT). В этом разделе показано, как это сделать.

Обычно основная функция приложения создается системой сборки и помещается в скрытый файл. Поэтому первым шагом является настройка проекта не для автоматического создания этой функции. Для этого необходимо определить символ DISABLE_XAML_GENERATED_MAIN в свойствах проекта.

Инструкции по C#

Перейдите к свойствам> (выберите все конфигурации и все платформы)> Создайте>условные символы компиляции и вставьте в символ DISABLE_XAML_GENERATED_MAIN.

Так как проект просто не создал функцию Main , проект не будет создан в данный момент. Поэтому второй и последний шаг — реализовать собственную версию этой функции в файле исходного кода.

Добавьте новый элемент проекта класса типа в проект и назовите его Program.cs. Внутри Program.csзамените код class Program {} собственной реализацией. Пример используемого кода см Program.cs . в примере AppLifecycle.

Инструкции по C++/WinRT

Перейдите к свойствам> (выберите свойства конфигурации и все платформы)> Свойства>конфигурации C/C++>Preprocessor Preprocessor>, измените значение и добавьте символ DISABLE_XAML_GENERATED_MAIN.

Так как мы просто не позволили проекту автоматически создавать функцию wWinMain , проект не будет создаваться в данный момент. Поэтому второй и последний шаг — реализовать собственную версию этой функции в файле исходного кода.

Добавьте ссылку на пакет NuGet Microsoft.Windows.ImplementationLibrary и обновите файлы исходного pch.h App.xaml.cpp кода проекта. Пример используемого кода см. в примере AppLifecycle. Обязательно измените пространство имен в winrt::CppWinUiDesktopInstancing::implementation::App соответствии с конкретным проектом.

Чтобы устранить ошибку C2872: "Microsoft": неоднозначный символ", измените значение using namespace Microsoft::UI::Xaml; using namespace winrt::Microsoft::UI::Xaml;на . И внесите дополнительные аналогичные изменения using в директивы.

Единый вход в Application.OnLaunched

Альтернативой использованию Main или wWinMain является выполнение единой логики в методе Application.OnLaunched класса App.

Внимание

Это позволяет упростить приложение в Application.OnLaunched . Тем не менее, много зависит от того, что делает ваше приложение. Если вы собираетесь в конечном итоге перенаправляться, а затем завершать текущий экземпляр, то вы захотите избежать выполнения каких-либо операций сброса (или даже работы, которые требуют явной отмены). В таких случаях Приложение.OnLaunched может быть слишком поздно, и вы можете предпочесть выполнять работу в функции Main или wWinMain приложения.

// App.xaml.cs in a Windows App SDK (WinUI 3) app
...
protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    // If this is the first instance launched, then register it as the "main" instance.
    // If this isn't the first instance launched, then "main" will already be registered,
    // so retrieve it.
    var mainInstance = Microsoft.Windows.AppLifecycle.AppInstance.FindOrRegisterForKey("main");

    // If the instance that's executing the OnLaunched handler right now
    // isn't the "main" instance.
    if (!mainInstance.IsCurrent)
    {
        // Redirect the activation (and args) to the "main" instance, and exit.
        var activatedEventArgs =
            Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
        await mainInstance.RedirectActivationToAsync(activatedEventArgs);
        System.Diagnostics.Process.GetCurrentProcess().Kill();
        return;
    }

    m_window = new MainWindow();
    m_window.Activate();
}
// pch.h in a Windows App SDK (WinUI 3) app
...
#include <winrt/Microsoft.Windows.AppLifecycle.h>
...

// App.xaml.h
...
struct App : AppT<App>
{
    ...
    winrt::fire_and_forget OnLaunched(Microsoft::UI::Xaml::LaunchActivatedEventArgs const&);
    ...
}

// App.xaml.cpp
...
using namespace winrt;
using namespace Microsoft::Windows::AppLifecycle;
...
winrt::fire_and_forget App::OnLaunched(LaunchActivatedEventArgs const&)
{
    // If this is the first instance launched, then register it as the "main" instance.
    // If this isn't the first instance launched, then "main" will already be registered,
    // so retrieve it.
    auto mainInstance{ AppInstance::FindOrRegisterForKey(L"main") };

    // If the instance that's executing the OnLaunched handler right now
    // isn't the "main" instance.
    if (!mainInstance.IsCurrent())
    {
        // Redirect the activation (and args) to the "main" instance, and exit.
        auto activatedEventArgs{ AppInstance::GetCurrent().GetActivatedEventArgs() };
        co_await mainInstance.RedirectActivationToAsync(activatedEventArgs);
        ::ExitProcess(0);
        co_return;
    }

    window = make<MainWindow>();
    window.Activate();
}

Кроме того, можно вызвать AppInstance.GetInstances, чтобы получить коллекцию запущенных объектов AppInstance. Если число элементов в этой коллекции больше 1, основной экземпляр уже запущен, и вы должны перенаправить его.

Сопоставление типов файлов

В проекте пакета SDK для приложений Windows, чтобы указать точку расширения для сопоставления типов файлов, вы делаете те же параметры в Package.appxmanifest файле, что и для проекта UWP. Ниже приведены эти параметры.

Открыть Package.appxmanifest. В объявлениях выберите сопоставления типов файлов и нажмите кнопку "Добавить". Задайте следующие свойства.

Отображаемое имя: MyFile Name: myfile File type: .myf

Чтобы зарегистрировать сопоставление типов файлов, создайте приложение, запустите его и закройте его.

Разница возникает в императивном коде. В приложении UWP вы реализуете App::OnFileActivated для обработки активации файлов. Но в приложении пакета SDK для приложений Для Windows вы пишете код в App::OnLaunched, чтобы проверить тип расширенной активации (ExtendedActivationKind) активированного события args (AppInstance.GetActivatedEventArgs) и узнать, является ли активация активацией файла.

Если у приложения есть навигация, у вас уже будет код навигации в App::OnLaunched, и вам может потребоваться повторно использовать эту логику. Дополнительные сведения см. в статье "Необходимо ли реализовать навигацию по страницам?".

// App.xaml.cs in a Windows App SDK app
...
using Microsoft.Windows.AppLifecycle;
...
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
    if (activatedEventArgs.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.File)
    {
        ...
    }
    ...
}
// pch.h in a Windows App SDK app
...
#include <winrt/Microsoft.Windows.AppLifecycle.h>

// App.xaml.cpp
...
using namespace Microsoft::Windows::AppLifecycle;
...
void App::OnLaunched(LaunchActivatedEventArgs const&)
{
    auto activatedEventArgs{ AppInstance::GetCurrent().GetActivatedEventArgs() };
    if (activatedEventArgs.Kind() == ExtendedActivationKind::File)
    {
        ...
    }
    ...
}

OnActivated, OnBackgroundActivated и другие методы обработки активации

В приложении UWP для переопределения различных средств, с помощью которых можно активировать приложение, можно переопределить соответствующие методы в классе приложения, например OnFileActivated, OnSearchActivated или более общей OnActivated.

В приложении пакета SDK для приложений Windows в App.OnLaunched (или в любое время) можно вызвать (AppInstance.GetActivatedEventArgs) для получения активируемых событий args и проверить их, чтобы определить, как приложение было активировано.

Дополнительные сведения и пример кода см. в разделе сопоставления типов файлов выше. Вы можете применить тот же метод для любого типа активации, указанного в перечислении ExtendedActivationKind .