Prozessübergreifende Kommunikation (Interprocess Communication, IPC)

In diesem Thema werden verschiedene Möglichkeiten zum Ausführen der Interprocess Communication (IPC) zwischen Windows App SDK Desktop-Apps und anderen Win32-Anwendungen erläutert. Da Windows App SDK Desktop-Apps als voll vertrauenswürdige Win32-Prozesse ausgeführt werden, haben sie direkten Zugriff auf alle IPC-Mechanismen auf Betriebssystemebene. Einige Mechanismen haben zusätzliche Anforderungen, wenn Apps mit MSIX verpackt werden, wie in den folgenden Abschnitten beschrieben.

App-Dienste

App-Dienste ermöglichen es Anwendungen, Dienste bereitzustellen, die im Hintergrund Eigenschaftensammlungen primitiver Datentypen (ValueSet) akzeptieren und zurückgeben. Komplexe Objekte können übergeben werden, wenn sie serialisiert sind.

App-Dienste können entweder außerhalb des Prozesses als Hintergrundaufgabe oder im Prozess innerhalb der Vordergrundanwendung ausgeführt werden.

Note

App-Dienste erfordern eine verpackte App mit Paketidentität. Sie sind für Windows App SDK Apps verfügbar, die MSIX-Verpackung verwenden.

App-Dienste eignen sich am besten zum Teilen kleiner Datenmengen, wenn keine nahezu in Echtzeit erfolgende Übertragung erforderlich ist.

COM

COM ist ein verteiltes objektorientiertes System zum Erstellen binärer Softwarekomponenten, die interagieren und kommunizieren können. Als Entwickler verwenden Sie COM, um wiederverwendbare Softwarekomponenten und Automatisierungsebenen für eine Anwendung zu erstellen. COM-Komponenten können verarbeitet oder nicht verarbeitet werden, und sie können über ein Client- und Servermodell kommunizieren. Out-of-Process-COM-Server werden seit langem als Mittel für die Kommunikation zwischen Objekten verwendet.

Verpackte Anwendungen mit der runFullTrust Fähigkeit können Out-of-Process-COM-Server für IPC über das Paketmanifest registrieren. Dies wird als verpacktes COM bezeichnet.

Windows App SDK Desktop-Apps werden als voll vertrauenswürdige Prozesse ausgeführt, sodass sie auch COM-Server direkt über die Windows-Registrierung registrieren und verwenden können, genau wie herkömmliche Win32-Anwendungen.

Filesystem

BroadFileSystemAccess

Verpackte Anwendungen können IPC mithilfe des allgemeinen Dateisystems ausführen, indem sie die broadFileSystemAccess eingeschränkte Funktion deklarieren. Diese Funktionalität gewährt Windows.Storage-APIs und Win32 FromApp APIs Zugriff auf das gesamte Dateisystem.

Standardmäßig ist IPC über das Dateisystem für verpackte Anwendungen auf die anderen mechanismen beschränkt, die in diesem Abschnitt beschrieben werden.

PublisherCacheFolder

PublisherCacheFolder ermöglicht verpackten Anwendungen das Deklarieren von Ordnern in ihrem Manifest, die von demselben Herausgeber für andere Pakete freigegeben werden können.

Der freigegebene Speicherordner hat die folgenden Anforderungen und Einschränkungen:

  • Daten im freigegebenen Speicherordner werden nicht gesichert oder übertragen.
  • Der Benutzer kann den Inhalt des freigegebenen Speicherordners löschen.
  • Sie können den freigegebenen Speicherordner nicht verwenden, um Daten zwischen Anwendungen verschiedener Anbieter freizugeben.
  • Sie können den freigegebenen Speicherordner nicht verwenden, um Daten für verschiedene Benutzer freizugeben.
  • Der freigegebene Speicherordner verfügt nicht über die Versionsverwaltung.

Wenn Sie mehrere Anwendungen veröffentlichen und nach einem einfachen Mechanismus zum Freigeben von Daten zwischen ihnen suchen, ist PublisherCacheFolder eine einfache dateisystembasierte Option.

Rohre

Rohre ermöglichen eine einfache Kommunikation zwischen einem Pipeserver und einem oder mehreren Pipeclients.

Anonyme Rohre und benannte Rohre werden mit den folgenden Einschränkungen unterstützt:

  • Standardmäßig werden benannte Pipes in verpackten Anwendungen nur zwischen Prozessen innerhalb desselben Pakets unterstützt, es sei denn, ein Prozess ist voll vertrauenswürdig.
  • Named Pipes können zwischen Paketen gemeinsam genutzt werden, wenn dabei die Richtlinien für die Freigabe benannter Objekte eingehalten werden.
  • Benannte Pipes in verpackten Apps sollten LOCAL\ im Pipe-Namen enthalten (z. B. \\.\pipe\LOCAL\<pipename>). Das LOCAL\-Segment beschränkt die Pipe auf die Anmeldesitzung des aufrufenden Benutzers und ist für MSIX-paketierte Apps erforderlich. Wenn Sie .NET-APIs wie NamedPipeServerStream" verwenden, übergeben Sie nur den LOCAL\<pipename> Teil – das \\.\pipe\ Präfix wird intern behandelt.

Desktop-Apps des Windows App SDK werden als voll vertrauenswürdige Prozesse ausgeführt, sodass sie benannte Pipes ohne die Beschränkung auf dasselbe Paket erstellen und verwenden können. Wenn Sie jedoch mit einer anderen verpackten App kommunizieren, die nicht voll vertrauenswürdig ist, gelten die oben genannten Einschränkungen weiterhin.

Benannte-Pipe-Beispiel (C#)

Das folgende Beispiel zeigt einen vollständigen Named-Pipe-Server und -Client als zwei Konsolenanwendungen. Da Windows App SDK Desktop-Apps voll vertrauenswürdige Prozesse sind, funktioniert named pipe IPC ohne spezielle Funktionen oder Manifesteinträge.

Um dieses Beispiel auszuprobieren, erstellen Sie zwei Konsolenanwendungsprojekte (mit dem Zielframework net8.0-windows und aktiviertem ImplicitUsings), und führen Sie zuerst den Server und dann den Client in einem separaten Terminal aus.

Pipe-Server — erstellt eine benannte Pipe und sendet Nachrichten an den Client zurück:

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.");

Pipe-Client – stellt eine Verbindung mit dem Server her und sendet Benutzereingaben:

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.");

Wenn Sie beide Anwendungen ausführen, sendet der Client Nachrichten, die der Server zurückgibt, und bestätigt die prozessübergreifende Kommunikation zwischen zwei voll vertrauenswürdigen Desktopprozessen ohne spezielle Konfiguration.

Registrierung

Die Registrierungsverwendung für IPC wird im Allgemeinen abgeraten, wird jedoch für vorhandenen Code unterstützt. Verpackte Anwendungen können nur auf Registrierungsschlüssel zugreifen, auf die sie über die Berechtigung zum Zugriff verfügen.

Verpackte Desktop-Apps (siehe Erstellen eines MSIX-Pakets aus Ihrem Code) nutzen Registrierungsvirtualisierung, sodass globale Schreibvorgänge in der Registrierung auf einen privaten Registrierungsbereich innerhalb des MSIX-Pakets beschränkt werden. Dies ermöglicht die Kompatibilität von Quellcode und minimiert gleichzeitig die auswirkungen auf die globale Registrierung und kann für IPC zwischen Prozessen im selben Paket verwendet werden. Wenn Sie die Registrierung verwenden müssen, wird dieses Modell bevorzugt, anstatt die globale Registrierung zu bearbeiten.

RPC

RPC kann verwendet werden, um eine verpackte Anwendung mit einem Win32-RPC-Endpunkt zu verbinden, vorausgesetzt, die verpackte Anwendung verfügt über die richtigen Funktionen zum Abgleichen der ACLs auf dem RPC-Endpunkt.

Benutzerdefinierte Berechtigungen ermöglichen OEMs und IHVs, beliebige Berechtigungen zu definieren, ihre RPC-Endpunkte damit per ACL zu schützen und diese Berechtigungen dann autorisierten Clientanwendungen zu gewähren. Eine vollständige Beispielanwendung finden Sie im CustomCapability-Beispiel .

RPC-Endpunkte können auch mit ACLs für bestimmte paketierte Anwendungen versehen werden, um den Zugriff auf den Endpunkt ausschließlich auf diese Anwendungen zu beschränken, ohne den Verwaltungsaufwand benutzerdefinierter Capabilities zu erfordern. Sie können die DeriveAppContainerSidFromAppContainerName-API verwenden, um eine SID von einem Paketfamiliennamen abzuleiten, und dann ACL den RPC-Endpunkt mit der SID, wie im CustomCapability-Beispiel gezeigt.

Gemeinsamer Speicher

Die Dateizuordnung kann zum Freigeben einer Datei oder eines Arbeitsspeichers zwischen zwei oder mehr Prozessen mit den folgenden Einschränkungen verwendet werden:

  • Standardmäßig werden Dateizuordnungen in verpackten Anwendungen nur zwischen Prozessen innerhalb desselben Pakets unterstützt, es sei denn, ein Prozess ist voll vertrauenswürdig.
  • Dateizuordnungen können über Pakete hinweg freigegeben werden, die den Richtlinien für die Freigabe benannter Objekte folgen.

Desktop-Apps des Windows App SDK werden als Prozesse mit voller Vertrauensstufe ausgeführt, sodass sie Dateizuordnungen für gemeinsam genutzten Speicher uneingeschränkt erstellen und verwenden können. Wenn Sie mit einer anderen verpackten App kommunizieren, die nicht voll vertrauenswürdig ist, verwenden Sie den in der Freigabe benannter Objekte beschriebenen ACL-Ansatz.

Gemeinsamer Speicher wird empfohlen, um große Datenmengen effizient zu teilen und zu bearbeiten.

Loopback

Loopback bezeichnet den Prozess, mit einem Netzwerkserver zu kommunizieren, der auf localhost lauscht (die Loopback-Adresse).

Um die Sicherheit und Netzwerkisolation aufrechtzuerhalten, werden Loopbackverbindungen für IPC standardmäßig für verpackte Anwendungen blockiert. Sie können Loopbackverbindungen zwischen vertrauenswürdigen verpackten Anwendungen mithilfe von Funktionen und Manifesteigenschaften aktivieren.

  • Alle verpackten Anwendungen, die an Loopbackverbindungen teilnehmen, müssen die privateNetworkClientServer Funktion in ihren Paketmanifesten deklarieren.
  • Zwei verpackte Anwendungen können über Loopback kommunizieren, indem LoopbackAccessRules innerhalb ihrer Paketmanifeste deklariert werden.
    • Jede Anwendung muss die andere in der LoopbackAccessRules auflisten. Der Client deklariert eine "Out"-Regel für den Server, und der Server deklariert "in"-Regeln für seine unterstützten Clients.

Note

Der Paketfamilienname, der zum Identifizieren einer Anwendung in diesen Regeln erforderlich ist, finden Sie über den Paketmanifest-Editor in Visual Studio während der Entwicklungszeit, über Partner Center für Anwendungen, die über die Microsoft Store veröffentlicht wurden, oder über den Befehl "Get-AppxPackage PowerShell" für bereits installierte Anwendungen.

Entpackte Anwendungen und Dienste besitzen keine Paketidentität, sodass sie nicht in LoopbackAccessRules deklariert werden können. Sie können eine verpackte Anwendung so konfigurieren, dass sie über Loopback mit entpackten Anwendungen und Diensten über CheckNetIsolation.exeverbunden wird. Dies ist jedoch nur für Querladen- oder Debuggingszenarien möglich, in denen Sie lokalen Zugriff auf den Computer haben und über Administratorrechte verfügen.

  • Wenn eine verpackte Anwendung eine Verbindung zu einer nicht verpackten Anwendung oder einem Dienst herstellt, führen Sie CheckNetIsolation.exe LoopbackExempt -a -n=<PACKAGEFAMILYNAME> aus, um eine Loopback-Ausnahme für die verpackte Anwendung hinzuzufügen.
  • Wenn eine entpackte Anwendung oder ein Dienst eine Verbindung mit einer verpackten Anwendung herstellt, führen Sie die Ausführung aus CheckNetIsolation.exe LoopbackExempt -is -n=<PACKAGEFAMILYNAME> , um die verpackte Anwendung zum Empfangen eingehender Loopbackverbindungen zu aktivieren.
    • CheckNetIsolation.exe muss durchgehend ausgeführt werden, während die verpackte Anwendung auf Verbindungen lauscht.

Note

Der für die -n Kennzeichnung von CheckNetIsolation.exe erforderliche Paketfamilienname finden Sie über den Paketmanifest-Editor in Visual Studio während der Entwicklungszeit, über Partner Center für Anwendungen, die über die Microsoft Store veröffentlicht wurden, oder über den Befehl "Get-AppxPackage PowerShell" für bereits installierte Anwendungen.

Auswählen eines IPC-Mechanismus

In der folgenden Tabelle sind die IPC-Mechanismen und ihre besten Anwendungsfälle zusammengefasst:

Mechanismus Am besten geeignet für: Anforderungen
App-Dienste Kleiner Datenaustausch mit Immobilientaschen Verpackte App mit Paketidentität
COM Wiederverwendbare Komponenten, Automatisierungsebenen None (Win32) oder Paketmanifest (Verpacktes COM)
Named Pipes Streambasierte bidirektionale Kommunikation Keine für voll vertrauenswürdige Apps
Gemeinsamer Speicher Große Daten, hohe Leistung Keine für voll vertrauenswürdige Apps
RPC Verteilte Client-/Serverprogramme ACLs müssen den Zugriff zulassen
Registrierung Kompatibilität mit Legacy-Code Entmutigt für neuen Code
Loopback Netzwerkbasierte Protokolle (TCP/UDP) privateNetworkClientServer Funktion für verpackte Apps