Windows アプリ SDKを使用したマルチインスタンス アプリ

既定では、Windows アプリ SDK デスクトップ アプリは複数のインスタンスを同時に実行できます。 各インスタンスは、個別のプロセスとして実行されます。 Microsoft.Windows.AppLifecycle.AppInstance クラスを使用して、この動作を制御し、インスタンスを登録し、既存のインスタンスを検出し、アクティブ化をリダイレクトできます。

マルチインスタンス管理のシナリオ

  • 単一インスタンスの強制 — 既に実行されているインスタンスに新しいアクティブ化をリダイレクトします。
  • キーベースのルーティング — 異なるファイルまたは URI を特定のインスタンス (ドキュメントごとに 1 つのインスタンスなど) にルーティングします。
  • インスタンス検出 - 実行中のすべてのインスタンスを列挙して作業を調整します。

キーを使用してインスタンスを登録する

アプリの AppInstance.FindOrRegisterForKey メソッドでMainを使用してキーを要求します。 キーが既に別のインスタンスによって登録されている場合は、アクティブ化をリダイレクトできます。 次のカスタム Main メソッドは、XAML 初期化の前に Program.csに入ります。

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

}

Note

カスタム 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() (非同期)
カスタム メイン エントリ ポイント 必須 必須 (同じアプローチ)