Win32: Wie bekomme ich den Prozess / Thread, der einen Mutex besitzt?

7

Ich arbeite an einer Anwendung, von der immer nur eine Instanz existieren muss. Dafür gibt es mehrere Möglichkeiten:

  • Überprüfen Sie laufende Prozesse für einen, der unserem EXE-Namen entspricht (unzuverlässig)
  • Finde das Hauptfenster (unzuverlässig, und ich habe nicht immer ein Hauptfenster)
  • Erstellen Sie einen Mutex mit einem eindeutigen Namen (GUID)

Die Mutex-Option scheint mir die zuverlässigste und eleganteste zu sein.

Bevor jedoch meine zweite Instanz beendet wird, möchte ich eine Nachricht an die bereits laufende Instanz senden. Dazu benötige ich einen Handle für den Thread (oder den Prozess), der den Mutex besitzt.

Es scheint jedoch keine API-Funktion zu geben, um den Ersteller / Eigentümer eines bestimmten Mutex zu erhalten. Überspringe ich es gerade? Gibt es eine andere Möglichkeit, zu diesem Thread / Prozess zu gelangen? Gibt es einen anderen Weg, dies zu tun?

Update : Dieser Typ sendet einfach eine Nachricht an all laufende Prozesse. Ich denke, das ist möglich, aber ich mag es nicht wirklich ...

    
Thomas 22.12.2009, 16:02
quelle

5 Antworten

4

Ich glaube nicht, dass es eine triviale Möglichkeit gibt, den tatsächlichen Eigentümer eines Mutex zu lösen, aber der Prozess, dem er gehört, kann andere sekundäre Elemente erstellen, deren Lebenszeiten damit verbunden sind. Es gibt viele Mechanismen, die geeignet sind, um ohne einen Hauptbildschirm zurückzugreifen.

  1. Registrieren Sie ein Objekt in der COM Running Object Table. Clients, die den Mutex nicht übernehmen können, können den Besitzer über das ROT suchen und zum Besitzer zurückrufen. Ein File Moniker sollte hier zur Registrierung geeignet sein.
  2. Erstellen Sie einen Teil des gemeinsam genutzten Speichers, der Standortdetails für den Besitzerprozess enthält. Schreiben Sie von dort aus den Prozess- und Thread-Handle eines Threads in den Puffer, der Windows-Nachrichten empfangen kann, und verwenden Sie dann PostThreadMessage (), um eine Benachrichtigung zu senden. Jeder andere konkurrierende Prozess kann den gemeinsamen Speicher für schreibgeschützte öffnen, um zu bestimmen, wo eine Windows-Nachricht gesendet werden soll.
  3. Hören Sie im Besitzerprozess auf einen Socket oder eine benannte Pipe zu. Wahrscheinlich übertrieben und nicht gut für Ihre Bedürfnisse.
  4. Verwenden Sie eine freigegebene Datei mit Sperren. Ich mag das nicht, weil der Besitzer abfragen muss, und er wird N andere potentielle Prozesse, die versuchen könnten, den Besitzer zur gleichen Zeit zu kontaktieren, nicht elegant behandeln.

Hier sind Referenzlinks für die ersten beiden Optionen.

  1. IRunningObjectTable @ MSDN , Datei-Moniker @ MSDN
  2. Benennen von freigegebenem Speicher @ MSDN
  3. erstellen
meklarian 22.12.2009, 16:35
quelle
10

Damit sollten Sie mit der ursprünglichen Anfrage beginnen, um einen Prozess zu erhalten, der einen Mutex besitzt.

Es ist in C #, aber die Win32-Aufrufe sind gleich.

%Vor%     
GalacticJello 22.12.2009 17:59
quelle
2

Ich habe nie verstanden, warum es sinnvoll ist, einen Mutex zu verwenden, der keine Signalfunktion besitzt. Ich würde stattdessen ein Ereignis (mit CreateEvent) erstellen, das die gleichen Eigenschaften wie das Erstellen eines Mutex hat (dh mit einem Namen, dass das Objekt bereits existiert), aber Sie können das Ereignisflag im neuen Prozess so lange wie das Original setzen Prozess wartet auf das Event-Flag, es kann benachrichtigt werden, wenn es sich selbst aufwecken muss.

    
tyranid 22.12.2009 16:18
quelle
2

Erstellen Sie einen gemeinsamen Speicherbereich mit dem festen Namen:

Ссылка

Dann können Sie jede gewünschte Struktur einfügen, einschließlich Prozess-ID, HWND usw.

Es gibt eine portable Option : Erstellen Sie einen Socket an einem Port (mit einer festen Nummer) und warten Sie (accept) darauf. Die zweite Instanz der App wird fehlschlagen, da der Port bereits vergeben ist. Dann kann sich die zweite Instanz mit dem Socket der primären Instanz verbinden und alle gewünschten Informationen senden.

Ich hoffe, das hilft ...

    
Daniel Nikolić 18.11.2010 15:13
quelle
1

Sie können es immer auf UNIX-Art machen und eine "pid" -Datei erstellen, indem Sie die Prozess-ID der aktuell laufenden Instanz in diese Datei einfügen. Lassen Sie dann die App die Datei beim Beenden löschen.

Beim Start einer neuen Instanz sollte überprüft werden, ob der Prozess in der PID-Datei auch tatsächlich aktiv ist (falls die Anwendung abnormal beendet wird und die Datei nicht gelöscht wird)

    
Eric Petroelje 22.12.2009 16:22
quelle