Migrazione delle funzionalità del ciclo di vita dell'applicazione

Questo argomento contiene indicazioni sulla migrazione nell'area del ciclo di vita dell'applicazione.

API importanti

Riepilogo delle differenze tra API e/o funzionalità

Le app Universal Windows Platform) (UWP) sono a istanza singola per impostazione predefinita; le app Windows App SDK (WinUI 3) sono a istanza multipla per impostazione predefinita.

Un'app UWP ha metodi App come OnFileActivated, OnSearchActivated, OnActivated e OnBackgroundActivated che indicano implicitamente come l'app è stata attivata; in un'app Windows App SDK, in App.OnLaunched (o in qualsiasi metodo), bisogna chiamare (AppInstance.GetActivatedEventArgs) per recuperare gli argomenti dell'evento di attivazione e controllarli per determinare come l'app è stata attivata.

Vedere anche la riga Attività in background in nella tabella dell'argomento Cosa è supportato durante la migrazione dalla piattaforma UWP a WinUI 3.

App a istanza singola

Le app Universal Windows Platform (UWP) sono a istanza singola per impostazione predefinita (è possibile acconsentire esplicitamente al supporto di più istanze); vedere Creare un'app UWP a istanze multiple).

Pertanto, il comportamento di un'app UWP a istanza singola prevede che la seconda (e successiva) volta che si avvia l'app, l'istanza corrente viene attivata. Supponiamo ad esempio che nell'app UWP è stata implementata la funzionalità di associazione del tipo di file. Se da Esplora file si apre un file (del tipo per cui l'app ha registrato un'associazione del tipo di file) e l'app è già in esecuzione, viene attivata l'istanza già in esecuzione.

Le app Windows App SDK (WinUI 3) le app, d'altra parte, sono a istanza multipla per impostazione predefinita. Quindi, per impostazione predefinita, la seconda (e successiva) volta che si avvia un'app Windows App SDK (WinUI 3), viene avviata una nuova istanza dell'app. Se ad esempio un'app Windows App SDK (WinUI 3) implementa l'associazione del tipo di file e da Esplora file si apre un file (del tipo corretto) mentre l'app è già in esecuzione, per impostazione predefinita viene avviata una nuova istanza dell'app.

Se si vuole che l'app Windows App SDK (WinUI 3) sia a istanza singola come l'app UWP, è possibile ignorare il comportamento predefinito descritto in precedenza. Si userà AppInstance.FindOrRegisterForKey e AppInstance.IsCurrent per determinare se l'istanza corrente è quella principale. In caso contrario, si chiamerà AppInstance.RedirectActivationToAsync per reindirizzare l'attivazione all'istanza principale già in esecuzione e quindi uscire dall'istanza corrente (senza creare né attivare la finestra principale).

Per altre informazioni, vedere Creazione di istanze dell'app con l'API ciclo di vita dell'app.

Importante

Il codice riportato di seguito funziona come previsto, purché sia destinato all'architettura x64. Si applica sia a C# che a C++/WinRT.

Creazione di istanze singole in Main o wWinMain

È consigliabile verificare la necessità di reindirizzare l'attivazione il prima possibile nell'esecuzione dell'app. Per questo motivo, è consigliabile eseguire la logica di creazione di istanze singole nella funzione Main (o wWinMain per C++/WinRT) dell'app. Questa sezione spiega come.

In genere la funzione Main dell'app viene generata automaticamente nel sistema di compilazione e posizionata in un file nascosto. Il primo passaggio consiste quindi nel configurare il progetto in modo che non generi automaticamente questa funzione. A tale scopo, definire il simbolo DISABLE_XAML_GENERATED_MAIN nelle Proprietà del progetto.

Istruzioni per C#

Andare su Proprietà> (selezionare Tutte le configurazioni e Tutte le piattaforme) >Build>Simboli di compilazione condizionale e incollare il simbolo DISABLE_XAML_GENERATED_MAIN.

Poiché è stato appena impedito al progetto di generare automaticamente una funzione Main, al momento il progetto non verrà compilato. Il secondo e l'ultimo passaggio consiste quindi nell'implementare la propria versione di tale funzione in un file del codice sorgente.

Aggiungere un nuovo elemento di progetto di tipo Classe al progetto e denominarlo Program.cs. All'interno di Program.cs, sostituire il codice class Program {} con la propria implementazione. Per un esempio di codice da utilizzare, vedere Program.cs nel AppLifecycle.

Istruzioni per C++/WinRT

Andare su Proprietà> (selezionare Tutte le configurazioni e Tutte le piattaforma) >Proprietà di configurazione>C/C++>Preprocessore>Definizioni del preprocessore, Modificare il valore e aggiungere il simbolo DISABLE_XAML_GENERATED_MAIN.

Poiché è stato appena impedito al progetto di generare automaticamente una funzione wWinMain, al momento il progetto non verrà compilato. Il secondo e l'ultimo passaggio consiste quindi nell'implementare la propria versione di tale funzione in un file del codice sorgente.

Aggiungere un riferimento al pacchetto NuGet Microsoft.Windows.ImplementationLibrary e aggiornare i file del codice sorgente pch.h e App.xaml.cpp del progetto. Per un esempio di codice da utilizzare, vedere l'esempio di AppLifecycle. Assicurarsi di modificare lo spazio dei nomi in winrt::CppWinUiDesktopInstancing::implementation::App in base al progetto specifico).

Per risolvere l'errore C2872: Microsoft: simbolo ambiguo, modificare using namespace Microsoft::UI::Xaml; in using namespace winrt::Microsoft::UI::Xaml;. E apportare eventuali ulteriori modifiche simili alle direttive using.

Creazione di istanze singole in Application.OnLaunched

Un'alternativa all'uso di Main o wWinMain è quella di eseguire la logica di creazione di istanze singole nel metodo Application.OnLaunched della classe App.

Importante

Questa operazione in Application.OnLaunched può semplificare l'app. Tuttavia, molto dipende dalle altre operazioni eseguite dall'app. Se si intende terminare il reindirizzamento e quindi terminare l'istanza corrente, è consigliabile evitare di eseguire qualsiasi lavoro temporaneo (o anche un lavoro che richiede l'annullamento esplicito). In casi simili, Application.OnLaunched potrebbe essere tardivo ed è consigliabile eseguire il lavoro nella funzione Main o wWinMain dell'app.

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

In alternativa, è possibile chiamare AppInstance.GetInstances per recuperare una raccolta di oggetti AppInstance in esecuzione. Se il numero di elementi nella raccolta è maggiore di 1, l'istanza principale è già in esecuzione ed è necessario il reindirizzamento a quella istanza.

Associazione del tipo di file

In un progetto Windows App SDK, per specificare il punto di estensione per un'associazione del tipo di file, occorre seguire le stesse impostazioni nel file Package.appxmanifest del progetto UWP. Ecco queste impostazioni.

Package.appxmanifest aperti. In Dichiarazioni, scegliere Associazioni del tipo di file e fare clic su Aggiungi. Imposta le proprietà seguenti.

Nome visualizzato: MyFile Nome: myfile Tipo di file: .myf

Per registrare l'associazione del tipo di file, compilare l'app, avviarla e chiuderla.

La differenza riguarda il codice imperativo. In un'app UWP, si implementa App::OnFileActivated per gestire l'attivazione dei file. Ma in un'app Windows App SDK, si scrive il codice in App::OnLaunched per controllare il tipo di attivazione estesa (ExtendedActivationKind) degli argomenti dell'evento di attivazione (AppInstance.GetActivatedEventArgs) e vedere se l'attivazoìione è un'attivazione di file.

Nota

Non usare l'oggetto Microsoft.UI.Xaml.LaunchActivatedEventArgs trasferito su App::OnLaunched per determinare il tipo di attivazione, perché segnala "Avvia" in modo incondizionato.

Se l'app ha lo spostamento, il codice di spostamento sarà già disponibile in App::OnLaunched e potrebbe essere necessario riutilizzare tale logica. Per altre informazioni, vedere Devo implementare la navigazione della pagina?

// 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 e altri metodi di gestione dell'attivazione

In un'app UWP, per ignorare i vari mezzi con cui puoi è possibile attivare l'app, si possono ignoraare i metodi corrispondenti nella classe App, ad esempio OnFileActivated, OnSearchActivated o il più generico OnActivated.

In un'app a Windows App SDK, in App.OnLaunched (o in effetti in qualsiasi momento) è possibile chiamare (AppInstance.GetActivatedEventArgs) per recuperare gli argomenti dell'evento di attivazione e controllarli per determinare come l'app è stata attivata.

Vedere la sezione Associazione del tipo di file in precedenza per maggiori dettagli e un esempio di codice. È possibile applicare la stessa tecnica per qualsiasi tipo di attivazione specificato dall'enumerazione ExtendedActivationKind.