具有Windows 应用 SDK的多实例应用

默认情况下,Windows 应用 SDK桌面应用可以同时运行多个实例。 每个实例作为单独的进程运行。 您可以使用 Microsoft.Windows.AppLifecycle.AppInstance 类来控制此行为,以注册实例、检测现有实例并重定向激活。

多实例管理场景

  • 单实例强制 实施 - 将新激活重定向到已运行的实例。
  • 基于密钥的路由 - 将不同的文件或 URI 路由到特定实例(例如,每个文档一个实例)。
  • 实例发现 - 枚举所有正在运行的实例以协调工作。

使用密钥注册实例

在您的应用的 Main 方法中使用 AppInstance.FindOrRegisterForKey 来声明一个密钥。 如果密钥已由另一个实例注册,则可以重定向激活。 以下自定义 Main 方法应放在 Program.cs 中,并且位于任何 XAML 初始化之前:

using Microsoft.Windows.AppLifecycle;

public static class Program
{

[STAThread]
static async Task Main(string[] args)
{
    // Required before calling any other Windows App SDK or WinRT API
    // from a custom entry point.
    WinRT.ComWrappersSupport.InitializeComWrappers();

    // Determine a key for this activation
    string instanceKey = "main-instance";

    var activatedArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
    if (activatedArgs.Kind == ExtendedActivationKind.File)
    {
        var fileArgs = activatedArgs.Data as
            Windows.ApplicationModel.Activation.IFileActivatedEventArgs;
        // Use the file path as the instance key to route
        // each file to its own instance
        if (fileArgs?.Files is { Count: > 0 })
        {
            instanceKey = fileArgs.Files[0].Path;
        }
    }

    var instance = AppInstance.FindOrRegisterForKey(instanceKey);

    if (!instance.IsCurrent)
    {
        // Another instance owns this key — redirect activation to it
        await instance.RedirectActivationToAsync(activatedArgs);
        return; // Exit this process
    }

    // This instance owns the key — proceed with normal startup
    // Register for future redirected activations
    instance.Activated += OnActivated;

    Application.Start((p) =>
    {
        var context = new DispatcherQueueSynchronizationContext(
            DispatcherQueue.GetForCurrentThread());
        SynchronizationContext.SetSynchronizationContext(context);
        _ = new App();
    });
}

private static void OnActivated(object? sender, AppActivationArguments args)
{
    // Handle the redirected activation on the UI thread
    // For example, open the file or navigate to the URI
}

// App is the application type generated by the WinUI 3 project template
// (App.xaml / App.xaml.cs).
private partial class App : Microsoft.UI.Xaml.Application
{
}

}

注释

若要使用自定义 Main 方法,请禁用自动生成的入口点。 在 .csproj 中,将 <DefineConstants>$(DefineConstants);DISABLE_XAML_GENERATED_MAIN</DefineConstants> 设置为追加该符号而不覆盖现有定义。

强制实施单实例行为

若要使应用单实例化,请始终使用相同的密钥:

var instance = AppInstance.FindOrRegisterForKey("single-instance");

if (!instance.IsCurrent)
{
    await instance.RedirectActivationToAsync(
        AppInstance.GetCurrent().GetActivatedEventArgs());
    return;
}

列出正在运行的实例

使用 AppInstance.GetInstances() 来发现所有已注册的实例:

var instances = AppInstance.GetInstances();
foreach (var inst in instances)
{
    System.Diagnostics.Debug.WriteLine(
        $"Key: {inst.Key}, ProcessId: {inst.ProcessId}");
}

取消注册实例

实例关闭时,会自动删除注册。 您还可以显式地取消注册:

AppInstance.GetCurrent().UnregisterKey();

与 UWP 多实例的差异

功能 UWP Windows 应用 SDK
命名空间 Windows.ApplicationModel.AppInstance Microsoft.Windows.AppLifecycle.AppInstance
清单要求 SupportsMultipleInstances 属性 桌面应用无需此项
实例发现 AppInstance.GetInstances() AppInstance.GetInstances() (相同模式)
激活重定向 AppInstance.RedirectActivationTo() AppInstance.RedirectActivationToAsync() (异步)
自定义主入口点 必需 必需(采用相同方式)