Share via


應用程式生命週期功能移轉

本主題包含應用程式生命週期領域的移轉指南。

重要 API

API 和/或功能差異摘要

預設情況下,通用 Windows 平台 (UWP) 應用程式是單一執行個體; 預設情況下,Windows 應用程式 SDK (WinUI 3) 應用程式是多執行個體。

UWP 應用程式具有 App 方法,例如 OnFileActivated、OnSearchActivatedOnActivatedOnBackgroundActivated,可隱含地告訴您應用程式如何啟動;在 Windows 應用程式 SDK 應用程式中,在 App.OnLaunched (或任何方法中),呼叫 (AppInstance.GetActivatedEventArgs) 以擷取啟動的事件自變數,並檢查它們以判斷應用程式如何啟動。

另請參閱從 UWP 移轉到 WinUI 3 時支援的內容主題中表格中的背景任務行。

單一執行個體應用程式

通用 Windows 平台 (UWP) 應用程式預設為單一執行個體 (您可以選擇支援多個執行個體—請參閱建立多執行個體 UWP 應用程式)。

因此,單一執行個體 UWP 應用程式的行為方式是啟動第二次 (和後續) 時間,即會啟動目前的執行個體。 例如,在 UWP 應用程式中,您已實作檔案類型關聯功能。 如果從 檔案總管開啟檔案 (應用程式已註冊檔類型關聯的類型),且您的應用程式已在執行中,則會啟動該已執行中的執行個體。

另一方面,Windows 應用程式 SDK (WinUI 3) 應用程式預設為多重執行個體。 因此,根據預設,您啟動 Windows 應用程式 SDK (WinUI 3) 應用程式的第二個 (和後續) 時間,就會啟動應用程式的新執行個體。 例如,如果 Windows 應用程式 SDK (WinUI 3) 應用程式實作檔類型關聯,而且從檔案總管開啟檔案 (正確類型)時,該應用程式已在執行中,則預設會啟動應用程式的新執行個體。

如果您想要讓 Windows 應用程式 SDK (WinUI 3) 應用程式像 UWP 應用程式一樣成為單一執行個體,則可以覆寫上述的預設行為。 您將使用 AppInstance.FindOrRegisterForKey AppInstance.IsCurrent 來判斷目前的執行個體是否為主要執行個體。 如果不是,則您將呼叫 AppInstance.RedirectActivationToAsync,將啟用重新導向至已執行的主要執行個體,然後結束目前執行個體 (而不建立或啟動其主視窗)。

如需詳細資訊,請參閱應用程式生命週期 API 的應用程式執行個體。

重要

下列程式代碼會如預期般運作,前提是您以 x64 架構為目標。 這同時適用於 C# 和 C++/WinRT。

Main 或 wWinMain 中的單一執行個體

最好在應用程式的執行中儘早檢查重新導向啟用的需求。 基於這個理由,我們建議您在應用程式的 Main (或適用於 C++/WinRT 的 wWinMain) 函式中執行單一執行個體邏輯。 本章節將示範方式。

一般而言,應用程式的 Main 函式是由建置系統自動產生,並放入隱藏的檔案中。 因此,第一個步驟是將項目設定為不要自動產生該函式。 若要這樣做,您可以在專案屬性中定義符號 DISABLE_XAML_GENERATED_MAIN

C# 的指示

轉到屬性> (選擇 All ConfigurationsAll Platforms) >Build>Conditional compilation symbols和編譯符號,然後貼上符號 DISABLE_XAML_GENERATED_MAIN

因為我們剛剛防止專案自動產生 Main 函式,因此專案目前不會建置。 因此,第二個步驟和最後一個步驟是在原始程式碼檔案中實作我們自己版本的該函式。

類別類型的新專案專案新增至專案,並將它命名為Program.cs。 在 Program.cs 內,將程式代碼 class Program {} 取代為您自己的實作。 如需要使用的程式代碼範例,請參閱 Program.csAppLifecycle 範例

C++/WinRT 的指示

前往 Properties> (選擇 All ConfigurationsAll Platforms) >Configuration Properties>C/C++>Preprocessor>Preprocessor DefinitionsEdit 值,並加入符號 DISABLE_XAML_GENERATED_MAIN

因為我們剛剛防止專案自動產生 wWinMain 函式,因此專案目前不會建置。 因此,第二個步驟和最後一個步驟是在原始程式碼檔案中實作我們自己版本的該函式。

新增對 Microsoft.Windows.ImplementationLibrary NuGet 套件的引用,並更新專案的 pch.hApp.xaml.cpp 原始碼檔案。 如需要使用的程式代碼範例,請參閱 AppLifecycle 範例。 請務必變更 winrt::CppWinUiDesktopInstancing::implementation::App 中的命名空間,以符合您的特定專案。

若要解決「錯誤 C2872:'Microsoft':不明確的符號」,請變更 using namespace Microsoft::UI::Xaml;using namespace winrt::Microsoft::UI::Xaml;。 對指示詞進行任何其他類似的變更 using 指示。

Application.OnLaunched 中的單一執行個體

使用 MainwWinMain 的替代方法是在 App 類別的 Application.OnLaunched 方法中執行單一執行個體邏輯。

重要

Application.OnLaunched 中執行這項工作可以簡化您的應用程式。 不過,很多都取決於您的應用程式正在做什麼。 如果您最終要重新導向,然後終止目前的執行個體,則您會想要避免執行任何擲回工作 (或甚至需要明確復原的工作)。 在這種情況下,Application.OnLaunched 可能太晚,而且您可能偏好在應用程式的 MainwWinMain 函式中執行工作。

// 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,則您的主要執行個體已經執行中,您應該重新導向至該執行個體。

檔案類型關聯

在 Windows 應用程式 SDK 專案中,若要指定檔案類型關聯的擴充點,請在 Package.appxmanifest 檔案中進行與 UWP 專案相同的設定。 以下是這些設定。

開啟 [Package.appxmanifest]。 在聲明中,選擇檔案類型關聯,然後按一下新增。 設定下列屬性。

顯示名稱:MyFile 名稱:myfile 檔類型:.myf

若要註冊檔類型關聯,請建置應用程式、啟動它,然後關閉它。

差異在於命令式程序代碼。 在UWP應用程式中,您會實作 App::OnFileActivated 以處理檔案啟用。 在聲明中,選擇檔案類型關聯,然後按一下新增。但是在 Windows 應用程式 SDK 應用程式中,您在 App::OnLaunched 中編寫程式碼來檢查啟動事件參數 (AppInstance.GetActivatedEventArgs) 的擴充功能啟動類型 (ExtendedActivationKind),然後查看是否是文件啟動。

注意

請勿使用 Microsoft.UI.Xaml.LaunchActivatedEventArgs 傳遞至 App::OnLaunched 對象來判斷啟用種類,因為會無條件回報「啟動」。

如果您的應用程式具有導航功能,那麼您已經在 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 應用程式中,若要覆寫可以啟動應用程式的各種方式,您可以在 App 類別上覆寫對應的方法,例如 OnFileActivatedOnSearchActivated 或更一般 OnActivated

在 Windows 應用程式 SDK 應用程式中,在 App.OnLaunched 中,您可以呼叫 (AppInstance.GetActivatedEventArgs) 來擷取啟動的事件自變數,並檢查它們以判斷應用程式是如何啟動的。

如需詳細資訊和程式代碼範例,請參閱上面的檔案類型關聯一節。 您可以針對 ExtendedActivationKind 列舉所指定的任何啟用類型套用相同的技術。