Gestire l'attivazione del protocollo URI in un'app .NET

L'attivazione del protocollo (chiamata anche deep linking o attivazione URI) consente a un'altra app, a un browser o alla riga di comando di avviare l'app passando a un URI, myapp://action?param=valuead esempio .

Questo articolo illustra in modo specifico il codice per un'app macchine virtuali Windows. Per indicazioni complete, vedere l'articolo principale Gestire l'attivazione URI . Per informazioni dettagliate sull'attivazione avanzata con il SDK per app di Windows, vedere Attivazione avanzata con l'API del ciclo di vita dell'app.

Eseguire la registrazione per l'attivazione del protocollo

Devi registrare l'app per gestire l'attivazione del protocollo. Per un'app non in pacchetto, si esegue la registrazione nel codice. Per un'app in pacchetto, esegui la registrazione nel manifesto dell'app.

App non impacchettata

Per un'app di .NET non in pacchetto (impostazione predefinita macchine virtuali Windows/WinForms), registrare il protocollo all'avvio usando ActivationRegistrationManager. Le registrazioni sono per utente e persistono, quindi è sicuro chiamarlo a ogni avvio.

In App.xaml.cs, sostituzione 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);
}

Per pulire la registrazione (ad esempio, in un passaggio di disinstallazione), chiamare ActivationRegistrationManager.UnregisterForProtocolActivation("myapp", "").

App pacchettizzata

Per un'app di .NET in pacchetto, dichiarare il protocollo in Package.appxmanifest nell'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>

Assicurati che il uap spazio dei nomi XML sia dichiarato nell'elemento Package: xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10".

Gestire l'attivazione

Recuperare gli argomenti di attivazione usando AppInstance.GetCurrent(). GetActivatedEventArgs. L'esempio seguente include il codice per un'app di macchine virtuali Windows non in pacchetto, che chiama RegisterForProtocolActivation all'avvio. Le app pacchettizzate ricevono l'attivazione tramite la registrazione del manifest, per ignorare la RegisterForProtocolActivation chiamata.

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.
}

Annotazioni

Le app macchine virtuali Windows e Windows Forms devono chiamare AppInstance.GetCurrent().GetActivatedEventArgs() per recuperare i dati di attivazione URI. A differenza delle app C++ Win32, le app .NET non ricevono argomenti di attivazione tramite un parametro di avvio dall'entry-point.

Gestire il reindirizzamento a istanza singola

Se l'app deve eseguire una sola istanza alla volta, usare AppInstance.FindOrRegisterForKey per reindirizzare gli avvii URI successivi all'istanza in esecuzione:

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

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