Partilhar via


Migração da funcionalidade do ciclo de vida do aplicativo

Este tópico contém diretrizes de migração na área de ciclo de vida do aplicativo.

APIs importantes

Resumo das diferenças de API e/ou recursos

Por padrão, os aplicativos UWP (Plataforma Universal do Windows) são de instância única e os aplicativos do SDK do Aplicativo Windows (WinUI 3) são de várias instâncias.

Um aplicativo UWP tem métodos App como OnFileActivated, OnSearchActivated, OnActivated e OnBackgroundActivated que informam implicitamente como o aplicativo foi ativado. Em um aplicativo do SDK do Aplicativo Windows, em App.OnLaunched (ou em qualquer método), chame (AppInstance.GetActivatedEventArgs) para recuperar os argumentos de eventos ativados e verifique-os para determinar como o aplicativo foi ativado.

Confira também a linha Tarefas em segundo plano na tabela do tópico Recursos com suporte na migração do UWP para o WinUI 3.

Aplicativos de instância única

Por padrão, os aplicativos UWP (Plataforma Universal do Windows) são de instância única (é possível optar por dar suporte a várias instâncias. Confira Criar um aplicativo UWP de várias instâncias).

Portanto, a maneira como um aplicativo UWP de instância única se comporta é que na segunda (e próxima) vez que você o inicia, sua instância atual é ativada. Digamos, por exemplo, que no seu aplicativo UWP você implementou o recurso de associação de tipo de arquivo. Se você abrir um arquivo (do tipo para o qual o aplicativo registrou uma associação de tipo de arquivo) por meio do Explorador de Arquivos e o seu aplicativo já estiver em execução, essa instância já em execução será ativada.

Os aplicativos do SDK do Aplicativo Windows (WinUI 3), por outro lado, são de várias instâncias por padrão. Dessa forma, por padrão, na segunda (e próxima) vez que você inicia um aplicativo do SDK do Aplicativo Windows (WinUI 3), uma nova instância do aplicativo é iniciada. Se, por exemplo, um aplicativo do SDK do Aplicativo Windows (WinUI 3) implementar a associação de tipo de arquivo e, por meio do Explorador de Arquivos, você abrir um arquivo (do tipo certo) enquanto esse aplicativo já estiver em execução, por padrão, uma nova instância do aplicativo será iniciada.

Caso deseje que o aplicativo do SDK do Aplicativo Windows (WinUI 3) seja de instância única como o aplicativo UWP, substitua o comportamento padrão descrito acima. Você usará AppInstance.FindOrRegisterForKey e AppInstance.IsCurrent para determinar se a instância atual é a instância principal. Caso contrário, você chamará AppInstance.RedirectActivationToAsync para redirecionar a ativação para a instância principal já em execução e sairá da instância atual (sem criar nem ativar a janela principal).

Para obter mais informações, confira Instanciação de aplicativo com a API de ciclo de vida do aplicativo.

Importante

O código mostrado abaixo funciona conforme o esperado, desde que o destino seja a arquitetura x64. Isso se aplica ao C# e ao C++/WinRT.

Instanciação única em Main ou wWinMain

É melhor verificar se há a necessidade de redirecionar a ativação o mais cedo possível na execução do aplicativo. Por esse motivo, recomendamos que você execute a lógica de instanciação única na função Main (ou wWinMain no C++/WinRT) do aplicativo. Esta seção mostra como fazer isso.

Normalmente, a função Main do aplicativo é gerada automaticamente pelo sistema de build e colocada em um arquivo oculto. Portanto, a primeira etapa é configurar seu projeto para não gerar automaticamente essa função. Para fazer isso, defina o símbolo DISABLE_XAML_GENERATED_principal em Propriedades do projeto.

Instruções para o C#

Acesse Propriedades> (selecione Todas as Configurações e Todas as Plataformas) >Criar>Símbolos de compilação condicional e cole o símbolo DISABLE_XAML_GENERATED_MAIN.

Como acabamos de impedir que o projeto gere automaticamente uma função Main, o projeto não será compilado no momento. Portanto, a segunda e a última etapa é implementar nossa versão dessa função em um arquivo de código-fonte.

Adicione um novo item de projeto do tipo Class ao projeto e dê a ele o nome Program.cs. Dentro de Program.cs, substitua o código class Program {} pela sua implementação. Para ver um exemplo do código a ser usado, confira Program.cs na amostra de AppLifecycle.

Instruções para o C++/WinRT

Acesse Propriedades> (selecione Todas as Configurações e Todas as Plataformas) >Propriedades de Configuração>C/C++>Pré-processador>Definições de Pré-processador, edite o valor e adicione o símbolo DISABLE_XAML_GENERATED_MAIN.

Como acabamos de impedir que o projeto gere automaticamente uma função wWinMain, o projeto não será compilado no momento. Portanto, a segunda e a última etapa é implementar nossa versão dessa função em um arquivo de código-fonte.

Adicione uma referência ao pacote NuGet Microsoft.Windows.ImplementationLibrary e atualize os arquivos de código-fonte pch.h e App.xaml.cpp do projeto. Para ver um exemplo do código a ser usado, confira a amostra de AppLifecycle. Lembre-se de alterar o namespace em winrt::CppWinUiDesktopInstancing::implementation::App de acordo com o projeto específico.

Para resolver o “erro C2872: ‘Microsoft’: símbolo ambíguo”, altere using namespace Microsoft::UI::Xaml; para using namespace winrt::Microsoft::UI::Xaml;. Além disso, faça outras alterações semelhantes às diretivas using.

Instanciação única em Application.OnLaunched

Uma alternativa ao uso de Main ou wWinMain é executar a lógica de instanciação única no método Application.OnLaunched da classe App.

Importante

Realizar esse trabalho em Application.OnLaunched pode simplificar seu aplicativo. No entanto, grande parte disso depende do que mais o aplicativo está fazendo. Se você vai acabar redirecionando e, em seguida, encerrando a instância atual, o ideal será evitar realizar qualquer trabalho descartável (ou mesmo um trabalho que precise ser desfeito explicitamente). Em casos como esse, Application.OnLaunched pode ser tarde demais, e talvez você prefira realizar o trabalho na função Main ou wWinMain do aplicativo.

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

Como alternativa, você pode chamar AppInstance.GetInstances para recuperar uma coleção de objetos AppInstance em execução. Se o número de elementos nessa coleção for maior que 1, a instância principal já estará em execução e você deverá fazer o redirecionamento para ela.

Associação de tipo de arquivo

Em um projeto do SDK do Aplicativo Windows, para especificar o ponto de extensão para uma associação de tipo de arquivo, faça as mesmas configurações no arquivo Package.appxmanifest que faria para um projeto do UWP. Veja abaixo essas configurações.

Abra Package.appxmanifest. Em Declarações, escolha Associações de Tipo de Arquivo e clique em Adicionar. Defina as seguintes propriedades.

Nome de exibição: MyFile Nome: myfile Tipo de arquivo: .myf

Para registrar a associação de tipo de arquivo, crie o aplicativo, inicie-o e feche-o.

A diferença é vista no código imperativo. Em um aplicativo UWP, você implementa App::OnFileActivated para cuidar da ativação de arquivo. Mas em um aplicativo do SDK do Aplicativo Windows, você escreve o código em App::OnLaunched para verificar o tipo de ativação estendida (ExtendedActivationKind) dos argumentos de eventos ativados (AppInstance.GetActivatedEventArgs) e vê se a ativação é uma ativação de arquivo.

Observação

Não use o objeto Microsoft.UI.Xaml.LaunchActivatedEventArgs transmitido para App::OnLaunched a fim de determinar o tipo de ativação, pois ele relata “Launch” incondicionalmente.

Se o seu aplicativo tiver navegação, você já terá o código de navegação em App::OnLaunched, e o ideal será reutilizar essa lógica. Para obter mais informações, confira Preciso implementar a navegação de página?.

// 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 outros métodos de tratamento de ativação

Em um aplicativo UWP, para substituir os vários meios pelos quais seu aplicativo pode ser ativado, substitua os métodos correspondentes na classe App, como OnFileActivated, OnSearchActivated ou o OnActivated mais geral.

Em um aplicativo do SDK do Aplicativo Windows, em App.OnLaunched (ou, de fato, a qualquer momento), chame (AppInstance.GetActivatedEventArgs) para recuperar os argumentos de eventos ativados e verifique-os para determinar como o aplicativo foi ativado.

Confira a seção Associação de tipo de arquivo acima para ver mais detalhes e um exemplo de código. Você pode aplicar a mesma técnica a qualquer tipo de ativação especificado pela enumeração ExtendedActivationKind.