Migration des fonctionnalités de cycle de vie des applications

Cette rubrique contient des conseils relatifs à la migration dans la zone de cycle de vie des applications.

API importantes

Résumé des différences d’API et/ou de fonctionnalités

Les applications de plateforme Windows universelle (UWP) sont par défaut à instance unique ; les applications du SDK d’application Windows (WinUI 3) sont multi-instances par défaut.

Une application UWP a des méthodes App comme OnFileActivated, OnSearchActivated, OnActivated etOnBackgroundActivated, qui vous indiquent implicitement comment l’application a été activée. Dans une application du SDK d'application Windows, dans App.OnLaunched (ou dans n’importe quelle méthode), appelez (AppInstance.GetActivatedEventArgs) pour récupérer les arguments d’évènement activés et vérifiez-les pour déterminer comment l’application a été activée.

Consultez également la ligne Tâches en arrière-plan dans la rubrique Ce qui est pris en charge lors de la migration d’UWP vers WinUI 3.

Applications à instance unique

Les applications de plateforme Windows universelle (UWP) sont par défaut à instance unique (vous pouvez choisir de prendre en charge plusieurs instances, voir Créer une application UWP multi-instances).

Ainsi, la façon dont une application UWP à instance unique se comporte est que la deuxième fois que vous lancez, et les fois suivantes, votre instance actuelle est activée. Supposons par exemple que dans votre application UWP, vous avez implémenté la fonctionnalité d’association de type de fichier. Si, depuis l’Explorateur de fichiers, vous ouvrez un fichier (du type pour lequel l’application a inscrit une association de type de fichier) et que votre application est déjà en cours d’exécution, alors cette instance déjà en cours d’exécution est activée.

À l’inverse, les applications du SDK d’application Windows (WinUI 3) sont multi-instances par défaut. Par conséquent, par défaut, la deuxième fois que vous lancez une application Windows App SDK (WinUI 3), et les fois suivantes, une nouvelle instance de l’application est lancée. Si, par exemple, une application SDK d’application Windows (WinUI 3) implémente une association de types de fichiers et que, depuis l’Explorateur de fichiers, vous ouvrez un fichier (du type approprié) pendant que cette application est déjà en cours d’exécution, alors une nouvelle instance de l’application est lancée par défaut.

Si vous souhaitez que votre application SDK d'application Windows (WinUI 3) soit à instance unique comme votre application UWP, vous pouvez remplacer le comportement par défaut décrit ci-dessus. Utilisez AppInstance.FindOrRegisterForKey et AppInstance.IsCurrent pour déterminer si l’instance actuelle est l’instance principale. Si ce n’est pas le cas, alors appelez AppInstance.RedirectActivationToAsync pour rediriger l’activation vers l’instance principale déjà en cours d’exécution, puis quittez l’instance actuelle (sans créer ni activer sa fenêtre principale).

Pour plus d’informations, consultez Instancier des applications avec l’API de cycle de vie de l’application.

Important

Le code indiqué ci-dessous fonctionne comme prévu, à condition de cibler l’architecture x64. Cela s’applique à C# et à C++/WinRT.

Instanciation unique dans Main ou wWinMain

Il est préférable de vérifier la nécessité de rediriger l’activation dès que possible dans l’exécution de votre application. Pour cette raison, nous vous recommandons d’effectuer votre logique d’instanciation unique dans la fonction Main (ou wWinMain pour C++/WinRT) de votre application. Cette section vous montre comment procéder.

En règle générale, la fonction Main de votre application est générée automatiquement par le système de génération, et placée dans un fichier masqué. Par conséquent, la première étape consiste à configurer votre projet pour ne pas générer automatiquement cette fonction. Pour ce faire, vous définissez le symbole DISABLE_XAML_GENERATED_MAIN dans les Propriétés du projet.

Instructions pour C#

Accédez à Propriétés> (sélectionnez Toutes les configurations et Toutes les plateformes) >Générer>Symboles de compilation conditionnelle, puis collez le symbole DISABLE_XAML_GENERATED_MAIN.

Comme nous venons d’empêcher le projet de générer automatiquement une fonction Main, le projet ne sera pas généré pour le moment. Par conséquent, la deuxième et la dernière étape consiste à implémenter notre propre version de cette fonction dans un fichier de code source.

Ajoutez un nouvel élément de projet de type Class au projet et nommez-le Program.cs. Dans Program.cs, remplacez le code class Program {} par votre propre implémentation. Pour obtenir un exemple de code à utiliser, consultez Program.cs dans l’exemple AppLifecycle.

Instructions pour C++/WinRT

Accédez à Propriétés> (sélectionnez Toutes les configurations et Toutes les plateformes) >Propriétés de configuration>C/C++>Préprocesseur>Définitions de préprocesseur, Modifier la valeur et ajoutez le symbole DISABLE_XAML_GENERATED_MAIN.

Comme nous venons d’empêcher le projet de générer automatiquement une fonction wWinMain, le projet ne sera pas généré pour le moment. Par conséquent, la deuxième et la dernière étape consiste à implémenter notre propre version de cette fonction dans un fichier de code source.

Ajoutez une référence au package NuGet Microsoft.Windows.ImplementationLibrary et mettez à jour les fichiers de code source pch.h et App.xaml.cpp de votre projet. Pour obtenir un exemple du code à utiliser, consultez l’échantillon AppLifecycle. Veillez à modifier l’espace de noms en winrt::CppWinUiDesktopInstancing::implementation::App pour correspondre à votre projet particulier.

Pour résoudre « erreur C2872 : « Microsoft » : symbole ambigu », changez using namespace Microsoft::UI::Xaml; en using namespace winrt::Microsoft::UI::Xaml;. Et apportez d’autres modifications similaires aux directives using.

Instanciation unique dans Application.OnLaunched

Une alternative à l’utilisation de Main ou de wWinMain consiste à effectuer votre logique d’instanciation unique dans la méthode Application.OnLaunched de votre classeApp.

Important

Faire cette opération dans Application.OnLaunched peut simplifier votre application. Toutefois, beaucoup dépend de ce que fait votre application. Si votre but est de rediriger puis de mettre fin à l’instance actuelle, alors vous voudrez éviter d’effectuer un travail jetable (ou même un travail qui nécessite explicitement une annulation). Dans de tes cas, Application.OnLaunched peut être trop tard et vous pourrez préférer effectuer le travail dans la fonction Main ou wWinMain de votre application.

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

Vous pouvez également appeler AppInstance.GetInstances pour récupérer une collection d’objets AppInstanceen cours d’exécution. Si le nombre d’éléments de cette collection est supérieur à 1, votre instance principale est déjà en cours d’exécution et vous devez vous y rediriger.

Association de type de fichier

Dans un projet SDK d’application Windows, pour spécifier le point d’extension d’une association de type de fichier, définissez les paramètres de votre fichier Package.appxmanifest comme vous le feriez pour un projet UWP. Voici ces paramètres.

Ouvrir Package.appxmanifest. Dans Déclarations, choisissez Associations de type de fichier et cliquez sur Ajouter. Définissez les propriétés suivantes.

Nom d’affichage : MyFile Nom: myfile Type de fichier : .myf

Pour inscrire l’association de type de fichier, générez l’application, lancez-la et fermez-la.

La différence se produit dans le code impératif. Dans une application UWP, vous implémentez App::OnFileActivated pour gérer l’activation des fichiers. Toutefois, dans une application SDK d’application Windows, vous écrivez du code dans App::OnLaunched pour vérifier le type d’activation étendu (ExtendedActivationKind) des arguments d’évènement activés (AppInstance.GetActivatedEventArgs), et voir si l’activation est une activation de fichier.

Remarque

N’utilisez pas l’objet Microsoft.UI.Xaml.LaunchActivatedEventArgs transmis à App::OnLaunched pour déterminer le type d’activation, car il signale « Launch » sans condition.

Si votre application dispose d’une navigation, alors vous disposez déjà du code de navigation dans App::OnLaunchedet vous pourriez vouloir réutiliser cette logique. Pour plus d’informations, consultez Dois-je implémenter la navigation de page ?.

// 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 et autres méthodes de gestion des activations

Dans une application UWP, pour remplacer les différents moyens par lesquels votre application peut être activée, vous pouvez remplacer les méthodes correspondantes sur la classe de votre App, comme OnFileActivated, OnSearchActivatedou la plus générale OnActivated.

Dans une application SDK d’application Windows, dans App.OnLaunched (ou en fait à tout moment), vous pouvez appeler (AppInstance.GetActivatedEventArgs) pour récupérer les arguments d’évènement activés et les vérifier pour déterminer comment l’application a été activée.

Pour plus d’informations, et un exemple de code, consultez la section Association de type fichier ci-dessus. Vous pouvez appliquer la même technique pour tout type d’activation spécifié par l’énumération ExtendedActivationKind.