Communication interprocessus (IPC)

Cette rubrique explique différentes façons d’effectuer une communication interprocesseur (IPC) entre SDK d'application Windows applications de bureau et d’autres applications Win32. Étant donné que SDK d'application Windows applications de bureau s’exécutent en tant que processus Win32 de confiance totale, ils ont un accès direct à tous les mécanismes IPC au niveau du système d’exploitation. Certains mécanismes ont des exigences supplémentaires lorsque les applications sont empaquetées avec MSIX, comme indiqué dans les sections ci-dessous.

Services d’application

Les services d’application permettent aux applications d’exposer des services qui acceptent et renvoient en arrière-plan des ensembles de propriétés contenant des types primitifs (ValueSet). Les objets enrichis peuvent être transmis s’ils sont sérialisés.

Les services d’application peuvent s’exécuter soit dans un processus distinct en tant que tâche en arrière-plan, soit dans le processus de l’application au premier plan.

Note

Les services d’application nécessitent une application empaquetée avec une identité de package. Ils sont disponibles pour SDK d'application Windows applications qui utilisent l'empaquetage MSIX.

Les services d’application sont mieux utilisés pour partager de petites quantités de données où la latence en quasi temps réel n’est pas nécessaire.

COM

COM est un système distribué orienté objet permettant de créer des composants logiciels binaires qui peuvent interagir et communiquer. En tant que développeur, vous utilisez COM pour créer des composants logiciels réutilisables et des couches d’automatisation pour une application. Les composants COM peuvent être en cours ou hors processus, et ils peuvent communiquer via un modèle client et serveur . Les serveurs COM hors processus ont été utilisés depuis longtemps comme moyen de communication entre objets.

Les applications empaquetées avec la runFullTrust capacité peuvent enregistrer des serveurs COM hors processus pour la communication interprocessus via le manifeste de package. Il s’agit de COM packagé.

SDK d'application Windows applications de bureau s’exécutent en tant que processus de confiance totale, afin qu’elles puissent également inscrire et utiliser des serveurs COM directement via le Registre Windows, tout comme les applications Win32 traditionnelles.

Filesystem

BroadFileSystemAccess

Les applications empaquetées peuvent effectuer des communications interprocessus (IPC) à l’aide de l’accès étendu au système de fichiers en déclarant la capacité restreinte broadFileSystemAccess. Cette fonctionnalité accorde aux API Windows.Storage et aux API Win32 FromApp l’accès au système de fichiers étendu.

Par défaut, IPC via le système de fichiers pour les applications empaquetées est limité aux autres mécanismes décrits dans cette section.

PublisherCacheFolder

PublisherCacheFolder permet aux applications empaquetées de déclarer des dossiers dans leur manifeste qui peuvent être partagés avec d’autres packages par le même éditeur.

Le dossier de stockage partagé présente les exigences et restrictions suivantes :

  • Les données du dossier de stockage partagé ne sont ni sauvegardées ni synchronisées entre appareils.
  • L’utilisateur peut effacer le contenu du dossier de stockage partagé.
  • Vous ne pouvez pas utiliser le dossier de stockage partagé pour partager des données entre des applications provenant de différents éditeurs.
  • Vous ne pouvez pas utiliser le dossier de stockage partagé pour partager des données entre différents utilisateurs.
  • Le dossier de stockage partagé n’a pas de gestion des versions.

Si vous publiez plusieurs applications et que vous recherchez un mécanisme simple pour partager des données entre elles, publisherCacheFolder est une option simple basée sur le système de fichiers.

Tuyaux

Les canaux permettent une communication simple entre un serveur de canal et un ou plusieurs clients de canal.

Les canaux anonymes et les canaux nommés sont pris en charge avec les contraintes suivantes :

  • Par défaut, les canaux nommés dans les applications empaquetées sont pris en charge uniquement entre les processus du même package, sauf si un processus est de confiance totale.
  • Les canaux nommés peuvent être partagés entre les packages en suivant les instructions pour le partage d’objets nommés.
  • Le nom des canaux nommés dans les applications empaquetées doit inclure LOCAL\ (par exemple, \\.\pipe\LOCAL\<pipename>). Le LOCAL\ segment étend le canal vers la session de connexion de l’appelant et est requis pour les applications empaquetées MSIX. Lorsque vous utilisez des API .NET telles que NamedPipeServerStream, passez uniquement la partie LOCAL\<pipename> — le préfixe \\.\pipe\ est géré en interne.

Les applications de bureau SDK d'application Windows s’exécutent en tant que processus de confiance totale ; elles peuvent donc créer et utiliser des canaux nommés sans être soumises à la restriction du même package. Toutefois, si vous communiquez avec une autre application empaquetée qui n’a pas une confiance totale, les contraintes ci-dessus s’appliquent toujours.

Exemple de tube nommé (C#)

L’exemple suivant illustre un serveur de canal nommé complet et un client sous la forme de deux applications console. Étant donné que les applications de bureau SDK d'application Windows sont des processus de confiance complète, la communication interprocessus (IPC) via des canaux nommés fonctionne sans capacité particulière ni entrée de manifeste spéciale.

Pour essayer cet exemple, créez deux projets d’application console (ciblant net8.0-windows avec ImplicitUsings activé) et exécutez d’abord le serveur, puis le client dans un terminal distinct.

Serveur de tube — crée un tube nommé et renvoie les messages au client :

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

Client pipe — se connecte au serveur et envoie les entrées de l’utilisateur :

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

Lorsque vous exécutez les deux applications, le client envoie des messages que le serveur renvoie, confirmant la communication interprocessus entre deux processus de bureau de confiance totale sans configuration spéciale requise.

Registre

L’utilisation du Registre pour IPC est généralement déconseillée, mais elle est prise en charge pour le code existant. Les applications empaquetées peuvent accéder uniquement aux clés de Registre auxquelles elles sont autorisées à accéder.

Les applications de bureau empaquetées (voir Génération d’un package MSIX à partir de votre code) tirent parti de la virtualisation du Registre afin que les écritures de registre globales soient contenues dans une ruche privée au sein du package MSIX. Cela permet la compatibilité du code source tout en réduisant l’impact global du registre et peut être utilisée pour l’IPC entre les processus du même package. Si vous devez utiliser le Registre, ce modèle est préféré par rapport à la manipulation du registre global.

RPC

RPC peut être utilisé pour connecter une application empaquetée à un point de terminaison RPC Win32, à condition que l’application empaquetée dispose des fonctionnalités appropriées pour correspondre aux listes de contrôle d’accès sur le point de terminaison RPC.

Les fonctionnalités personnalisées permettent aux oem et aux IHV de définir des fonctionnalités arbitraires, de mettre à la liste de contrôle d’accès leurs points de terminaison RPC avec eux, puis d’accorder ces fonctionnalités aux applications clientes autorisées. Pour obtenir un exemple d’application complet, consultez l’exemple CustomCapability .

Les points de terminaison RPC peuvent également être soumis à des ACL pour des applications empaquetées spécifiques afin de limiter l’accès au point de terminaison uniquement à ces applications, sans nécessiter la charge de gestion de capacités personnalisées. Vous pouvez utiliser l’API DeriveAppContainerSidFromAppContainerName pour dériver un SID à partir d’un nom de famille de package, puis ACL le point de terminaison RPC avec le SID, comme indiqué dans l’exemple CustomCapability .

Mémoire partagée

Le mappage de fichiers peut être utilisé pour partager un fichier ou une mémoire entre deux processus ou plus avec les contraintes suivantes :

  • Par défaut, les mappages de fichiers dans les applications empaquetées sont pris en charge uniquement entre les processus au sein du même package, sauf si un processus est de confiance totale.
  • Les mappages de fichiers peuvent être partagés entre les packages en suivant les instructions pour le partage d’objets nommés.

SDK d'application Windows applications de bureau s’exécutent en tant que processus de confiance totale, afin qu’elles puissent créer et utiliser des mappages de fichiers de mémoire partagée sans restriction. Lorsque vous communiquez avec une autre application empaquetée qui ne bénéficie pas d’une confiance totale, utilisez l’approche ACL décrite dans Partage d’objets nommés.

La mémoire partagée est recommandée pour partager et manipuler efficacement de grandes quantités de données.

Bouclage

Le bouclage consiste à communiquer avec un serveur réseau qui écoute sur localhost (l’adresse de bouclage).

Pour maintenir la sécurité et l’isolation du réseau, les connexions loopback pour l’IPC sont bloquées par défaut pour les applications empaquetées. Vous pouvez activer les connexions loopback entre des applications empaquetées de confiance à l’aide de capacités et de propriétés du manifeste.

  • Toutes les applications empaquetées participant à des connexions de bouclage doivent déclarer la privateNetworkClientServer fonctionnalité dans leurs manifestes de package.
  • Deux applications empaquetées peuvent communiquer en boucle locale en déclarant LoopbackAccessRules dans leurs manifestes de package.
    • Chaque application doit répertorier l’autre dans son LoopbackAccessRules. Le client déclare une règle « sortante » destinée au serveur, et le serveur déclare des règles « entrantes » pour les clients qu’il prend en charge.

Note

Le nom de la famille de packages requis pour identifier une application dans ces règles est disponible via l’éditeur de manifeste de package dans Visual Studio pendant le développement, via l’Espace partenaires pour les applications publiées via le Microsoft Store, ou via la commande PowerShell Get-AppxPackage pour les applications déjà installées.

Les applications et services non empaquetés n’ont pas d’identité de package. Ils ne peuvent donc pas être déclarés dans LoopbackAccessRules. Vous pouvez configurer une application empaquetée pour vous connecter via un bouclage avec des applications et des services non empaquetés via CheckNetIsolation.exe, mais cela n’est possible que pour les scénarios de chargement indépendant ou de débogage où vous avez un accès local à l’ordinateur et que vous disposez de privilèges d’administrateur.

  • Si une application empaquetée se connecte à une application ou un service non empaqueté, exécutez cette opération CheckNetIsolation.exe LoopbackExempt -a -n=<PACKAGEFAMILYNAME> pour ajouter une exemption de bouclage pour l’application empaquetée.
  • Si une application ou un service non empaqueté se connecte à une application empaquetée, exécutez CheckNetIsolation.exe LoopbackExempt -is -n=<PACKAGEFAMILYNAME> pour permettre à l’application empaquetée de recevoir des connexions de bouclage entrantes.
    • CheckNetIsolation.exe devez être en cours d’exécution en continu pendant que l’application empaquetée écoute les connexions.

Note

Le nom de la famille de packages requis pour l’indicateur -n de CheckNetIsolation.exe est disponible via l’éditeur de manifeste de package dans Visual Studio pendant le développement, via l’Espace partenaires pour les applications publiées via le Microsoft Store, ou via la commande PowerShell Get-AppxPackage pour les applications déjà installées.

Choix d’un mécanisme IPC

Le tableau suivant récapitule les mécanismes IPC et leurs meilleurs cas d’usage :

Mécanisme Idéal pour Requirements
Services d’application Échange de données de petite taille avec des sacs de propriétés Application packagée avec identité de package
COM Composants réutilisables, couches d’automatisation Aucun (Win32) ou manifeste du package (COM packagé)
Canaux nommés Communication bidirectionnelle basée sur le flux Aucun pour les applications à confiance totale
Mémoire partagée Données volumineuses, hautes performances Aucun pour les applications de confiance totale
RPC Programmes client/serveur distribués Les listes de contrôle d’accès doivent autoriser l’accès
Registre Compatibilité du code hérité Déconseillé pour tout nouveau code
Bouclage Protocoles basés sur le réseau (TCP/UDP) privateNetworkClientServer fonctionnalité pour les applications empaquetées