Migration der Anwendungslebenszyklus-Funktionalität

Dieser Artikel enthält einen Migrationsleitfaden für den Anwendungslebenszyklus.

Wichtige APIs

Zusammenfassung der API- und/oder Funktionsunterschiede

UWP-Apps (Universelle Windows-Plattform) sind standardmäßig Einzelinstanzen-Apps. Windows App SDK-Apps (WinUI 3) sind standardmäßig Mehrinstanzen-Apps.

Eine UWP-App verfügt über App-Methoden wie OnFileActivated, OnSearchActivated, OnActivated und OnBackgroundActivated, die Ihnen implizit mitteilen, wie die App aktiviert wurde. Rufen Sie in einer Windows App SDK-App in App.OnLaunched (oder in einer beliebigen Methode) AppInstance.GetActivatedEventArgs auf, um die aktivierten Ereignisargumente abzurufen, und überprüfen Sie sie, um zu bestimmen, wie die App aktiviert wurde.

Sehen Sie sich auch die Zeile Hintergrundtasks in der Tabelle unter Was beim Migrieren von UWP zu WinUI 3 unterstützt wird an.

Einzelinstanzen-Apps

UWP-Apps (Universelle Windows-Plattform) sind standardmäßig Einzelinstanzen-Apps. Unter Erstellen einer UWP-Mehrinstanzen-App erfahren Sie, wie Sie diese zur Mehrinstanzen-App machen.

Verhalten einer UWP-Einzelinstanzen-App: Beim zweiten (und jedem weiteren) Start wird die aktuelle Instanz aktiviert. Nehmen wir beispielsweise an, dass Sie in Ihrer UWP-App das Feature für die Dateitypzuordnung implementiert haben. Wenn Sie im Datei-Explorer eine Datei öffnen (des Typs, für den die App eine Dateitypzuordnung registriert hat) und Ihre App bereits ausgeführt wird, wird diese bereits ausgeführte Instanz aktiviert.

Windows App SDK-Apps (WinUI 3) sind hingegen standardmäßig Mehrinstanzen-Apps. Beim zweiten (und jedem weiteren) Start einer Windows App SDK-Apps (WinUI 3) wird eine neue Instanz der App gestartet. Wenn beispielsweise eine Windows App SDK-Apps (WinUI 3) die Dateitypzuordnung implementiert und im Datei-Explorer eine Datei (des richtigen Typs) geöffnet wird, während diese App bereits ausgeführt wird, wird standardmäßig eine neue Instanz der App gestartet.

Wenn Ihre Windows App SDK-Apps (WinUI 3) wie Ihre UWP-App instanziiert werden soll, können Sie das oben beschriebene Standardverhalten außer Kraft setzen. Sie verwenden AppInstance.FindOrRegisterForKey und AppInstance.IsCurrent, um zu bestimmen, ob die aktuelle Instanz die Hauptinstanz ist. Wenn das nicht der Fall ist, rufen Sie AppInstance.RedirectActivationToAsync auf, um die Aktivierung an die bereits ausgeführte Hauptinstanz umzuleiten und dann über die aktuelle Instanz zu beenden (ohne das Hauptfenster zu erstellen oder zu aktivieren).

Weitere Informationen finden Sie unter App-Instanziierung mit der App-Lebenszyklus-API.

Wichtig

Der unten gezeigte Code funktioniert wie erwartet, vorausgesetzt, Sie verwenden die x64-Architektur als Ziel. Das gilt sowohl für C# als auch für C++/WinRT.

Einzelinstanziierung in Main oder wWinMain

Es sollte so früh wie möglich bei der Ausführung Ihrer App geprüft werden, ob umgeleitet werden muss. Aus diesem Grund wird empfohlen, Ihre Einzelinstanziierungslogik in der Main-Funktion (oder wWinMain-Funktion für C++/WinRT) Ihrer App auszuführen. Die Vorgehensweise wird in diesem Abschnitt erläutert.

Normalerweise wird die Main-Funktion Ihrer App automatisch vom Buildsystem generiert und in eine ausgeblendete Datei eingefügt. Daher besteht der erste Schritt darin, Ihr Projekt so zu konfigurieren, dass diese Funktion nicht automatisch generiert wird. Dazu definieren Sie das Symbol DISABLE_XAML_GENERATED_MAIN in den Projekteigenschaften.

Anweisungen für C#

Wechseln Sie zu Eigenschaften, wählen Sie Alle Konfigurationen und Alle Plattformen und dann Erstellen>Symbole für bedingte Kompilierung aus, und fügen Sie das Symbol DISABLE_XAML_GENERATED_MAIN ein.

Da wir das Projekt gerade daran gehindert haben, eine Main-Funktion automatisch zu generieren, kann das Projekt derzeit nicht kompiliert werden. Der zweite und letzte Schritt besteht also darin, unsere eigene Version dieser Funktion in einer Quellcodedatei zu implementieren.

Fügen Sie dem Projekt ein neues Projektelement des Typs Klasse hinzu, und nennen Sie es Program.cs. Ersetzen Sie in Program.cs den Code class Program {} durch Ihre eigene Implementierung. Ein Beispiel für den zu verwendenden Code finden Sie unter Program.cs im AppLifecycle-Beispiel.

Anweisungen für C++/WinRT

Wechseln Sie zu Eigenschaften, wählen Sie Alle Konfigurationen und Alle Plattformen und dann Konfigurationseigenschaften>C/C++>Präprozessor>Präprozessordefinitionen aus. Bearbeiten Sie den Wert, und fügen Sie das Symbol DISABLE_XAML_GENERATED_MAIN hinzu.

Da wir das Projekt gerade daran gehindert haben, eine wWinMain-Funktion automatisch zu generieren, kann das Projekt derzeit nicht kompiliert werden. Der zweite und letzte Schritt besteht also darin, unsere eigene Version dieser Funktion in einer Quellcodedatei zu implementieren.

Fügen Sie einen Verweis auf das NuGet-Paket Microsoft.Windows.ImplementationLibrary hinzu, und aktualisieren Sie die Quellcodedateien pch.h und App.xaml.cpp Ihres Projekts. Ein Beispiel für den zu verwendenden Code finden Sie im AppLifecycle-Beispiel. Achten Sie darauf, den Namespace in winrt::CppWinUiDesktopInstancing::implementation::App an Ihr jeweiliges Projekt anzupassen.

Um „Fehler C2872: "Microsoft": Mehrdeutiges Symbol“ zu beheben, ändern Sie using namespace Microsoft::UI::Xaml; in using namespace winrt::Microsoft::UI::Xaml;. Nehmen Sie dann weitere ähnliche Änderungen an using-Anweisungen vor.

Einzelinstanziierung in Application.OnLaunched

Eine Alternative zur Verwendung von Main oder wWinMain besteht darin, Ihre Einzelinstanziierungslogik in der Application.OnLaunched-Methode Ihrer App-Klasse auszuführen.

Wichtig

Diese in Application.OnLaunched zu implementieren kann Ihre App vereinfachen. Vieles hängt jedoch davon ab, was Ihre App sonst noch tut. Wenn Sie eine Umleitung verwenden und dann die aktuelle Instanz beenden, sollten Sie vermeiden, dass zu überarbeitende oder rückgängig zu machende Arbeit vorhanden ist. In solchen Fällen ist Application.OnLaunched möglicherweise ungeeignet, und Sie sollten die Arbeit in der Main- oder wWinMain-Funktion Ihrer App erledigen.

// 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();
}

Alternativ können Sie AppInstance.GetInstances aufrufen, um eine Collection der ausgeführten AppInstance-Objekte abzurufen. Wenn die Anzahl der Elemente in dieser Collection größer als 1 ist, wird die Hauptinstanz bereits ausgeführt, und Sie sollten zu diesem umleiten.

Dateitypzuordnung

Wenn Sie in einem Windows App SDK-Projekt den Erweiterungspunkt für eine Dateitypzuordnung angeben möchten, legen Sie die gleichen Einstellungen in Ihrer Package.appxmanifest-Datei wie bei einem UWP-Projekt fest. Hier sind diese Einstellungen:

Öffnen Sie Package.appxmanifest. Wählen Sie unter Deklarationen die Option Dateitypzuordnungen aus, und klicken Sie auf Hinzufügen. Legen Sie die folgenden Eigenschaften fest.

Anzeigename: MyFile Name: myfile Dateityp: .myf

Um die Dateitypzuordnung zu registrieren, kompilieren Sie die App, starten Sie sie, und schließen Sie sie.

Der Unterschied entsteht im imperativen Code. In einer UWP-App implementieren Sie App::OnFileActivated, um die Dateiaktivierung zu verarbeiten. In einer Windows App SDK-App schreiben Sie jedoch Code in App::OnLaunched, um den erweiterten Aktivierungstyp (ExtendedActivationKind) der aktivierten Ereignisargumente (AppInstance.GetActivatedEventArgs) zu überprüfen und festzustellen, ob es sich bei der Aktivierung um eine Dateiaktivierung handelt.

Hinweis

Verwenden Sie nicht das Objekt Microsoft.UI.Xaml.LaunchActivatedEventArgs, das an App::OnLaunched übergeben wird, um die Aktivierungsart zu bestimmen, da es bedingungslos „Launch“ meldet.

Wenn Ihre App über eine Navigation verfügt, ist bereits Navigationscode in App::OnLaunched vorhanden, und Sie sollten diese Logik wiederverwenden. Weitere Informationen finden Sie unter Muss ich die Seitennavigation implementieren?.

// 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 und andere Methoden für die Aktivierungsverarbeitung

Wenn Sie in einer UWP-App die verschiedenen Möglichkeiten außer Kraft setzen möchten, über die Ihre App aktiviert werden kann, können Sie entsprechende Methoden für ihre App-Klasse außer Kraft setzen, z. B. OnFileActivated, OnSearchActivated oder die allgemeinere OnActivated-Methode.

In einer Windows App SDK-App können Sie in App.OnLaunched (bzw. jederzeit) AppInstance.GetActivatedEventArgs aufrufen, um die Aktivierungsereignisargumente abzurufen und anhand dieser zu bestimmen, wie Ihre App aktiviert wurde.

Weitere Informationen und ein Codebeispiel finden Sie im Abschnitt Dateitypzuordnung weiter oben. Sie können dieselbe Technik für jede Aktivierungsart anwenden, die durch die ExtendedActivationKind-Enumeration angegeben wird.