2010-08-23 3 views
2

J'ai une application à instance unique (C#, WPF, .net3.51). La vérification si l'application est déjà instanciée est effectuée via un Mutex. Si l'application est déjà en cours d'exécution, j'ouvre une nouvelle fenêtre à partir de l'instance d'application déjà ouverte. Cela fonctionne bien jusqu'à présent.Envoi d'arguments à une instance d'application qui réside dans un autre processus

Cependant, en raison d'une extension d'application, je dois maintenant envoyer les e.Args (ou au moins la première chaîne) à l'instance en cours d'exécution qui réside dans un autre processus. Comment cela est-il le mieux fait?

Informations supplémentaires
Actuellement, j'utiliser une fenêtre enregistré globaly message que je transmets à toutes les applications ouvertes via PostMessage (HWND_BROADCAST). Mon application recherche ce message et ouvre une nouvelle fenêtre, si ce message est reçu. Une idée serait de définir un paramètre de PostMessage. Cependant j'ai trouvé beaucoup d'informations déroutantes sur ce sujet, donc je n'ai pas eu le courage d'aller dans cette direction. En plus de cela, j'ai pensé à remplacer l'appel global de PostMessage par une autre logique d'activation, car l'appel global semble avoir des effets secondaires déplaisants.

Répondre

9

Vous pouvez utiliser des canaux nommés, qui ont été ajoutés à la BCL dans .NET 3.5.

Créez le serveur de canaux nommé (receveur d'arguments) dans l'instance en cours d'exécution et créez le client de canal nommé (expéditeur d'argument) dans l'application en double. Ensuite, envoyez les arguments du client au serveur.

L'une ou l'autre extrémité du canal nommé peut être créée en C/C++ si nécessaire. Voir la fonction Win32 CreateNamedPipe. Ci-dessous un exemple simple où le client et le serveur fonctionnent tous les deux dans un seul programme (le GUID "FD1AF2B4 ..." ci-dessous n'est qu'un identifiant unique pour éviter les collisions avec des tuyaux déjà existants sur le système).

class Program 
{ 
    static void Main(string[] args) 
    { 
     Thread writerThread = new Thread(new ThreadStart(WriterThread)); 
     writerThread.Start(); 

     Thread readerThread = new Thread(new ThreadStart(ReaderThread)); 
     readerThread.Start(); 
    } 

    static void ReaderThread() 
    { 
     NamedPipeServerStream server = new NamedPipeServerStream("FD1AF2B4-575A-46E0-8DF5-8AB368CF6645"); 
     server.WaitForConnection(); 

     using (var reader = new BinaryReader(server)) 
     { 
      string arguments = reader.ReadString(); 
      Console.WriteLine("Received: {0}", arguments); 
     } 
    } 

    static void WriterThread() 
    { 
     NamedPipeClientStream client = new NamedPipeClientStream("FD1AF2B4-575A-46E0-8DF5-8AB368CF6645"); 
     client.Connect(Timeout.Infinite); 

     using (var writer = new BinaryWriter(client)) 
     { 
      writer.Write("/foo /bar:33 /baz:quux"); 
     } 
    } 
} 
+0

Il est plutôt préférable d'obtenir '[assembly: Guid]' valeur d'attribut que quelqu'un dur code – abatishchev

+1

Je suppose que pipe noms et prises ne sont que deux solutions fiables, cependant, je préfère les pipes nommés, pouvez-vous me dire pourquoi vous avez déclaré "overkill", quel est le problème avec le tuyau nommé? Je demande juste par curiosité, sinon votre réponse est parfaite. –

+1

@Akash: Je suppose que dire "overkill" était exagéré :) Oui, cela fonctionnera de manière fiable. Je pense que ce que j'essayais de dire, c'est que cela ressemble à beaucoup de code juste pour envoyer une chaîne d'une application à l'autre. C'est certainement mieux que d'utiliser les API Win32 crues! J'ai mis à jour ma réponse pour supprimer le "overkill". –

Questions connexes