Manipular a ativação do protocolo URI em um aplicativo .NET

A ativação do protocolo (também chamada de vinculação profunda ou ativação de URI) permite que outro aplicativo, um navegador ou a linha de comando iniciem seu aplicativo navegando até um URI, como myapp://action?param=value.

Este artigo mostra o código especificamente para um aplicativo WPF. Para obter diretrizes completas, consulte o artigo Processar ativação de URI principal. Para obter detalhes completos sobre a ativação rica com o SDK do Aplicativo Windows, consulte Ativação rica com a API do ciclo de vida do aplicativo.

Registrar-se para ativação de protocolo

Você deve registrar seu aplicativo para lidar com a ativação do protocolo. Para um aplicativo não empacotado, registre-se no código. Para um aplicativo empacotado, registre-se no manifesto do aplicativo.

Aplicativos não empacotados

Para um aplicativo de .NET não empacotado (a configuração padrão WPF/WinForms), registre seu protocolo na inicialização usando ActivationRegistrationManager. Os registros são por usuário e persistem, portanto, é seguro chamar isso em cada inicialização.

Em App.xaml.cs, substitua OnStartup:

using Microsoft.Windows.AppLifecycle;

protected override void OnStartup(StartupEventArgs e)
{
    // Register the URI scheme "myapp://" for this app.
    // For the logo, pass the exe path + resource index (or "" to use the default icon).
    string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName ?? "";
    string logo = string.IsNullOrEmpty(exePath) ? "" : exePath + ",0";
    ActivationRegistrationManager.RegisterForProtocolActivation(
        "myapp",                // URI scheme (no "://")
        logo,                   // logo: exe path + resource index, or "" for default icon
        "My App",               // display name for the protocol
        exePath);               // path of this EXE; pass "" to default to the current process

    base.OnStartup(e);
}

Para limpar o registro (por exemplo, em uma etapa de desinstalação), chame ActivationRegistrationManager.UnregisterForProtocolActivation("myapp", "").

Aplicativo empacotado

Para um aplicativo de .NET empacotado, declare o protocolo em Package.appxmanifest no elemento <Applications><Application>:

<Applications>
  <Application ...>
    <Extensions>
      <uap:Extension Category="windows.protocol">
        <uap:Protocol Name="myapp">
          <uap:DisplayName>My App</uap:DisplayName>
        </uap:Protocol>
      </uap:Extension>
    </Extensions>
  </Application>
</Applications>

Verifique se o uap namespace XML foi declarado no Package elemento: xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10".

Gerenciar a ativação

Recupere os argumentos de ativação usando AppInstance.GetCurrent(). GetActivatedEventArgs. O exemplo a seguir inclui código para um aplicativo de WPF não empacotado, que chama RegisterForProtocolActivation na inicialização. Os aplicativos empacotados recebem ativação por meio do registro de manifesto, de maneira que eles possam ignorar a chamada RegisterForProtocolActivation.

using Microsoft.Windows.AppLifecycle;
using Windows.ApplicationModel.Activation;

protected override void OnStartup(StartupEventArgs e)
{
    // Unpackaged apps only: register the protocol at startup.
    // Packaged apps (MSIX): skip these lines — the manifest handles registration.
    string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName ?? "";
    string logo = string.IsNullOrEmpty(exePath) ? "" : exePath + ",0";
    ActivationRegistrationManager.RegisterForProtocolActivation(
        "myapp", logo, "My App", exePath);

    // Get the activation args for this specific launch.
    AppActivationArguments args = AppInstance.GetCurrent().GetActivatedEventArgs();
    if (args?.Kind == ExtendedActivationKind.Protocol)
    {
        var protocolArgs = (ProtocolActivatedEventArgs)args.Data;
        HandleProtocolActivation(protocolArgs.Uri);
    }

    base.OnStartup(e);
}

private void HandleProtocolActivation(Uri uri)
{
    // Navigate to or open content based on uri.AbsolutePath or uri.Query.
}

Note

aplicativos WPF e Windows Forms devem chamar AppInstance.GetCurrent().GetActivatedEventArgs() para recuperar dados de ativação de URI. Ao contrário dos aplicativos C++ Win32, .NET aplicativos não recebem argumentos de ativação por meio de um parâmetro de ponto de entrada de inicialização.

Manipular redirecionamento de instância única

Se o aplicativo deve executar apenas uma instância de cada vez, use AppInstance.FindOrRegisterForKey para redirecionar as inicializações subsequentes do URI para a instância em execução:

protected override void OnStartup(StartupEventArgs e)
{
    string exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName ?? "";
    string logo = string.IsNullOrEmpty(exePath) ? "" : exePath + ",0";
    ActivationRegistrationManager.RegisterForProtocolActivation(
        "myapp", logo, "My App", exePath);

    // Try to claim the "main" key. If another instance already has it, redirect and exit.
    AppInstance currentInstance = AppInstance.FindOrRegisterForKey("main");
    if (!currentInstance.IsCurrent)
    {
        var activationArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
        // Run the async redirect on a thread-pool thread to avoid a potential deadlock
        // with the WPF SynchronizationContext. Signal completion via an event so that
        // this code path exits cleanly without re-entering the STA message pump.
        var redirectCompleted = new System.Threading.ManualResetEventSlim(false);
        System.Threading.Tasks.Task.Run(async () =>
        {
            await currentInstance.RedirectActivationToAsync(activationArgs);
            redirectCompleted.Set();
        });
        redirectCompleted.Wait();
        Shutdown();
        return;
    }

    // This is the first instance. Subscribe to future activations.
    currentInstance.Activated += OnActivated;
    base.OnStartup(e);
}

private void OnActivated(object sender, AppActivationArguments args)
{
    Dispatcher.Invoke(() =>
    {
        if (args.Kind == ExtendedActivationKind.Protocol)
        {
            var protocolArgs = (ProtocolActivatedEventArgs)args.Data;
            HandleProtocolActivation(protocolArgs.Uri);
        }
        MainWindow?.Activate();
    });
}

Para obter mais informações sobre instanciamento de aplicativos, consulte a instanciação de aplicativo com a API de ciclo de vida do aplicativo.