このトピックでは、Windows アプリ SDK デスクトップ アプリと他の Win32 アプリケーションの間でプロセス間通信 (IPC) を実行するさまざまな方法について説明します。 Windows アプリ SDKデスクトップ アプリは完全信頼 Win32 プロセスとして実行されるため、すべての OS レベルの IPC メカニズムに直接アクセスできます。 一部のメカニズムには、以下のセクションで説明するように、アプリを MSIX でパッケージ化する場合に追加の要件があります。
アプリ サービス
アプリ サービスを使用すると、アプリケーションは、バックグラウンドでプリミティブ (ValueSet) のプロパティ バッグを受け入れて返すサービスを公開できます。 リッチ オブジェクトは、シリアル化されている場合に渡すことができます。
アプリ サービスは、バックグラウンド タスクとして、またはフォアグラウンド アプリケーション内でプロセス外で実行できます。
Note
アプリ サービスには、パッケージ ID を持つパッケージ アプリが必要です。 MSIX パッケージを使用するWindows アプリ SDK アプリで使用できます。
アプリ サービスは、ほぼリアルタイムの待機時間が必要ない少量のデータを共有するために最適です。
COM
COM は、対話および通信できるバイナリ ソフトウェア コンポーネントを作成するための分散オブジェクト指向システムです。 開発者は、COM を使用して、アプリケーションの再利用可能なソフトウェア コンポーネントとオートメーション レイヤーを作成します。 COM コンポーネントは、処理中でもプロセス外でも、 クライアントおよびサーバー モデルを介して通信できます。 アウトプロセス COM サーバーは、 オブジェクト間通信の手段として長い間使用されてきました。
runFullTrust機能を持つパッケージ 化されたアプリケーションは、パッケージ マニフェストを使用して IPC のアウトプロセス COM サーバーを登録できます。 これは Packaged COM と呼ばれます。
Windows アプリ SDKデスクトップ アプリは完全信頼プロセスとして実行されるため、従来の Win32 アプリケーションと同様に、Windows レジストリ経由で COM サーバーを直接登録して使用することもできます。
Filesystem
BroadFileSystemAccess
パッケージ化されたアプリケーションでは、制限された機能 broadFileSystemAccess 宣言することで、広範なファイルシステムを使用して IPC を実行できます。 この機能により、Windows.Storage API と Win32 FromApp API は、広範なファイル システムにアクセスできるようになります。
既定では、パッケージ化されたアプリケーションのファイルシステム経由の IPC は、このセクションで説明する他のメカニズムに制限されます。
パブリッシャー キャッシュ フォルダー
PublisherCacheFolder を使用すると、パッケージ化されたアプリケーションは、同じ発行元が他のパッケージと共有できるフォルダーをマニフェストで宣言できます。
共有ストレージ フォルダーには、次の要件と制限があります。
- 共有ストレージ フォルダー内のデータはバックアップもローミングもされません。
- ユーザーは、共有ストレージ フォルダーの内容をクリアできます。
- 共有ストレージ フォルダーを使用して、異なる発行元のアプリケーション間でデータを共有することはできません。
- 共有ストレージ フォルダーを使用して、異なるユーザー間でデータを共有することはできません。
- 共有ストレージ フォルダーにはバージョン管理がありません。
複数のアプリケーションを発行し、それらの間でデータを共有する簡単なメカニズムを探している場合、PublisherCacheFolder は単純なファイルシステム ベースのオプションです。
パイプ
パイプ を使用すると、パイプ サーバーと 1 つ以上のパイプ クライアント間の簡単な通信が可能になります。
匿名パイプ と 名前付きパイプ は、次の制約でサポートされています。
- 既定では、パッケージ 化されたアプリケーションの名前付きパイプは、プロセスが完全信頼でない限り、同じパッケージ内のプロセス間でのみサポートされます。
- 名前付きパイプは、名前 付きオブジェクトを共有するためのガイドラインに従って、パッケージ間で共有できます。
- パッケージ アプリの名前付きパイプは、パイプ名に
LOCAL\を含める必要があります (たとえば、\\.\pipe\LOCAL\<pipename>)。LOCAL\セグメントは、呼び出し元のログイン セッションにパイプのスコープを設定し、MSIX パッケージ アプリに必要です。NamedPipeServerStreamなどの.NET API を使用する場合は、LOCAL\<pipename>部分のみを渡します。\\.\pipe\プレフィックスは内部的に処理されます。
Windows アプリ SDKデスクトップ アプリは完全信頼プロセスとして実行されるため、同じパッケージ制限なしで名前付きパイプを作成して使用できます。 ただし、完全な信頼を持たない別のパッケージ アプリと通信している場合は、上記の制約が引き続き適用されます。
名前付きパイプの例 (C#)
次の例は、2 つのコンソール アプリケーションとしての完全な名前付きパイプ サーバーとクライアントを示しています。 Windows アプリ SDKデスクトップ アプリは完全信頼プロセスであるため、名前付きパイプ IPC は特別な機能やマニフェスト エントリなしで動作します。
この例を試すには、2 つのコンソール アプリ プロジェクト (net8.0-windowsが有効なImplicitUsingsを対象とする) を作成し、最初にサーバーを実行してから、クライアントを別のターミナルで実行します。
パイプ サーバー — 名前付きパイプを作成し、メッセージをクライアントにエコーバックします。
using System.Text;
string PipeName = @"LOCAL\WinAppSdkIpcDemo";
Console.WriteLine("Named Pipe Server");
Console.WriteLine($" Process ID: {Environment.ProcessId}");
Console.WriteLine($" User: {Environment.UserName}");
Console.WriteLine($" Pipe: \\\\.\\pipe\\{PipeName}");
Console.WriteLine();
using var server = new System.IO.Pipes.NamedPipeServerStream(
PipeName,
System.IO.Pipes.PipeDirection.InOut,
maxNumberOfServerInstances: 1,
System.IO.Pipes.PipeTransmissionMode.Message,
System.IO.Pipes.PipeOptions.Asynchronous);
Console.WriteLine("Waiting for client...");
await server.WaitForConnectionAsync();
Console.WriteLine("Client connected!");
byte[] buffer = new byte[4096];
while (server.IsConnected)
{
try
{
int bytesRead = await server.ReadAsync(buffer);
if (bytesRead == 0) break;
string received = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine($" Received: \"{received}\"");
if (received.Equals("QUIT", StringComparison.OrdinalIgnoreCase))
break;
// Echo the message back with the server's process ID
string reply = $"Echo from PID {Environment.ProcessId}: {received}";
await server.WriteAsync(Encoding.UTF8.GetBytes(reply));
await server.FlushAsync();
}
catch (IOException)
{
break;
}
}
Console.WriteLine("Done.");
パイプ クライアント : サーバーに接続し、ユーザー入力を送信します。
using System.Text;
string PipeName = @"LOCAL\WinAppSdkIpcDemo";
Console.WriteLine("Named Pipe Client");
Console.WriteLine($" Process ID: {Environment.ProcessId}");
Console.WriteLine();
using var client = new System.IO.Pipes.NamedPipeClientStream(
serverName: ".",
pipeName: PipeName,
System.IO.Pipes.PipeDirection.InOut,
System.IO.Pipes.PipeOptions.Asynchronous);
Console.WriteLine("Connecting...");
await client.ConnectAsync(timeout: 5000);
client.ReadMode = System.IO.Pipes.PipeTransmissionMode.Message;
Console.WriteLine("Connected! Type messages (or QUIT to exit):");
byte[] buffer = new byte[4096];
while (true)
{
Console.Write("> ");
string? input = Console.ReadLine();
if (string.IsNullOrEmpty(input)) continue;
await client.WriteAsync(Encoding.UTF8.GetBytes(input));
await client.FlushAsync();
if (input.Equals("QUIT", StringComparison.OrdinalIgnoreCase))
break;
int bytesRead = await client.ReadAsync(buffer);
string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine($" <- {response}");
}
Console.WriteLine("Done.");
両方のアプリケーションを実行すると、クライアントはサーバーがエコーバックするメッセージを送信し、特別な構成を必要とせず、2 つの完全信頼デスクトップ プロセス間のクロスプロセス通信を確認します。
レジストリ
IPC のレジストリの使用は一般に推奨されませんが、既存のコードではサポートされています。 パッケージ化されたアプリケーションは、アクセス許可を持つレジストリ キーにのみアクセスできます。
パッケージ化されたデスクトップ アプリ ( コードからの MSIX パッケージのビルドを参照) では 、グローバル レジストリ の書き込みが MSIX パッケージ内のプライベート ハイブに含まれるようレジストリ仮想化を利用します。 これにより、グローバル レジストリへの影響を最小限に抑えながらソース コードの互換性が実現し、同じパッケージ内のプロセス間の IPC に使用できます。 レジストリを使用する必要がある場合は、グローバル レジストリを操作するより、このモデルをお勧めします。
RPC
RPC は、パッケージ化されたアプリケーションが RPC エンドポイントの ACL と一致する適切な機能を備える場合に、パッケージ化されたアプリケーションを Win32 RPC エンドポイントに接続するために使用できます。
カスタム機能を使用すると、OEM と IHV は 任意の機能を定義し、 RPC エンドポイントを ACL にして、 それらの機能を承認されたクライアント アプリケーションに付与できます。 完全なサンプル アプリケーションについては、 CustomCapability サンプルを参照してください。
RPC エンドポイントは、カスタム機能の管理オーバーヘッドを必要とせずに、特定のパッケージ 化されたアプリケーションに対して ACL を使用して、エンドポイントへのアクセスをそれらのアプリケーションのみに制限することもできます。 DeriveAppContainerSidFromAppContainerName API を使用して、パッケージ ファミリ名から SID を派生させ、次に CustomCapability サンプルに示すように、SID を使用して RPC エンドポイントを ACL できます。
共有メモリ
ファイル マッピング を使用すると、次の制約を持つ 2 つ以上のプロセス間でファイルまたはメモリを共有できます。
- 既定では、パッケージ 化されたアプリケーションのファイル マッピングは、プロセスが完全に信頼されていない限り、同じパッケージ内のプロセス間でのみサポートされます。
- ファイル マッピングは、 名前付きオブジェクトを共有するためのガイドラインに従って、パッケージ間で共有できます。
Windows アプリ SDKデスクトップ アプリは完全信頼プロセスとして実行されるため、制限なく共有メモリ ファイル マッピングを作成して使用できます。 完全な信頼がない別のパッケージ アプリと通信する場合は、 名前付きオブジェクトの共有で説明されている ACL アプローチを使用します。
大量のデータを効率的に共有および操作するには、共有メモリをお勧めします。
Loopback
ループバックは、localhost (ループバック アドレス) でリッスンしているネットワーク サーバーと通信するプロセスです。
セキュリティとネットワークの分離を維持するために、パッケージ化されたアプリケーションでは、IPC のループバック接続が既定でブロックされます。 機能とマニフェスト プロパティを使用して、信頼されたパッケージ アプリケーション間のループバック接続を有効にすることができます。
- ループバック接続に参加しているすべてのパッケージ アプリケーションは、
privateNetworkClientServerで機能を宣言する必要があります。 - パッケージ マニフェスト内で LoopbackAccessRules を宣言することで、2 つのパッケージ 化されたアプリケーションがループバック経由で通信できます。
- 各アプリケーションは、その LoopbackAccessRules 内のもう一方を一覧表示する必要があります。 クライアントはサーバーの "out" ルールを宣言し、サーバーはサポートされているクライアントに対して "in" ルールを宣言します。
Note
これらのルールでアプリケーションを識別するために必要なパッケージ ファミリ名は、開発時にVisual Studioのパッケージ マニフェスト エディター、Microsoft Storeを介して発行されたアプリケーションのパートナー センター、または既にインストールされているアプリケーションの Get-AppxPackage PowerShell コマンドを使用して見つけることができます。
パッケージ化されていないアプリケーションとサービスにはパッケージ ID がないため、LoopbackAccessRules で宣言することはできません。 パッケージ化されていないアプリケーションとサービスを CheckNetIsolation.exe経由して ループバック経由で接続するようにパッケージ化されたアプリケーションを構成できますが、これは、コンピューターへのローカル アクセス権があり、管理者特権があるサイドロードまたはデバッグシナリオでのみ可能です。
- パッケージ化されていないアプリケーションがパッケージ化されていないアプリケーションまたはサービスに接続している場合は、
CheckNetIsolation.exe LoopbackExempt -a -n=<PACKAGEFAMILYNAME>実行して、パッケージ化されたアプリケーションのループバック除外を追加します。 - パッケージ化されていないアプリケーションまたはサービスがパッケージ化されたアプリケーションに接続している場合は、
CheckNetIsolation.exe LoopbackExempt -is -n=<PACKAGEFAMILYNAME>を実行して、パッケージ化されたアプリケーションが受信ループバック接続を受信できるようにします。- パッケージ 化されたアプリケーションが接続をリッスンしている間、CheckNetIsolation.exeは継続的に実行されている必要があります。
Note
-n の フラグに必要なパッケージ ファミリ名は、開発時にVisual Studioのパッケージ マニフェスト エディター、Microsoft Storeを介して発行されたアプリケーションのパートナー センター、または既にインストールされているアプリケーションの Get-AppxPackage PowerShell コマンドを使用して見つけることができます。
IPC メカニズムの選択
次の表は、IPC メカニズムとその最適なユース ケースをまとめたものです。
| メカニズム | 最適な用途 | Requirements |
|---|---|---|
| アプリ サービス | プロパティ バッグを使用した少量のデータ交換 | パッケージ ID を持つパッケージ アプリ |
| COM | 再利用可能なコンポーネント、自動化レイヤー | なし (Win32) またはパッケージ マニフェスト (パッケージ化された COM) |
| 名前付きパイプ | ストリームベースの双方向通信 | 完全信頼アプリの場合はなし |
| 共有メモリ | 大きなデータ、高パフォーマンス | 完全信頼アプリの場合はなし |
| RPC | 分散クライアント/サーバー プログラム | ACL はアクセスを許可する必要があります |
| レジストリ | 従来のコードの互換性 | 新しいコードでは推奨されません |
| Loopback | ネットワーク ベースのプロトコル (TCP/UDP) |
privateNetworkClientServer パッケージ アプリの機能 |
関連するコンテンツ
Windows developer