Hallo, ich habe hier folgendes Problem: Prozess A soll beim Start dafür sorgen, dass Prozess B nicht aktiv ist. Momentan mache ich das so, dass ich nach dem Prozess B suche und falls er vorhanden ist, dann schicke ich mit PostMessage() ein WM_CLOSE raus. Solange der Prozess B nur einmal läuft geht das - jedenfalls meistens! Habe ich aber zwei am laufen, dann wird immer nur einer beendet. Wenn ich dann mehrfach PostMessage() aufrufe, hängt sich Prozess A auf. Mit TerminateProcess() oder SendMessageTimeout() funktioniert es auch nicht. Wer hat den Holzhammer? Gruß Georg
1 | hWnd = FindWindowEx( NULL,NULL,NULL,m_szName ); |
2 | |
3 | if ( hWnd != NULL ) |
4 | {
|
5 | PostMessage( hWnd,WM_CLOSE,0,0 ); |
6 | |
7 | if ( WaitForSingleObject( hWnd,5000 ) != WAIT_OBJECT_0 ) |
8 | dwResult = TerminateProcess( hWnd,0 ); |
9 | |
10 | CloseHandle( hWnd ); |
11 | }
|
DAnke!
Ohne C zu kennen würde ich sagen du musst vorher überprüfen ob der Prozess überhaupt vorhanden ist
Jeder Prozess hat eine eigene ID auch wenn zweimal der gleiche gestartet wird bekommt jeder eine eigene ID. Wenn du nur einmal suchst bekommst du auch nur eine ID. Den Prozess mit dieser ID kannst du auch nur einmal "abschießen". Den Anderen mußt du nochmal suchen.
Georg schrieb: > Hallo, > > ich habe hier folgendes Problem: Prozess A soll beim Start dafür sorgen, > dass Prozess B nicht aktiv ist. Hmm, hmm, wer hat sich denn sowas ausgedacht? > Momentan mache ich das so, dass ich nach dem Prozess B suche und falls > er vorhanden ist, dann schicke ich mit PostMessage() ein WM_CLOSE raus. Schlägt fehl wenn B (in dem Moment) WM_CLOSE liest aber ignoriert oder als Reaktion eine Messagebox (Möchten Sie das Dokument speichern?) öffnet - vorzugsweise auf einem unerreichbaren Desktop. > Solange der Prozess B nur einmal läuft geht das - jedenfalls meistens! > Habe ich aber zwei am laufen, dann wird immer nur einer beendet. Wenn > ich dann mehrfach PostMessage() aufrufe, hängt sich Prozess A auf. Mit > TerminateProcess() oder SendMessageTimeout() funktioniert es auch nicht. > > Wer hat den Holzhammer? Der Holzhammer ist TerminateProzess, korrekt benutzt. Das ist wörtlich zu verstehen - d.h. man erzeugt undefiniertes Verhalten im System, genau wie im vom Holzhammer getroffenen Kopf. ;-) Sowas kann nur brauchbar funktionieren wenn A und B über ein definiertes Protokoll miteinander kooperieren, alles andere wird Probleme geben.
>Hmm, hmm, wer hat sich denn sowas ausgedacht? Ich, warum? >Schlägt fehl wenn B (in dem Moment) WM_CLOSE liest aber ignoriert oder >als Reaktion eine Messagebox (Möchten Sie das Dokument speichern?) >öffnet - vorzugsweise auf einem unerreichbaren Desktop. Kann nicht passieren, da Prozess B kein sichtbares Fenster hat - es handelt sich um einen 'Worker-Prozess', wenn man das so sagen darf. >Der Holzhammer ist TerminateProzess, korrekt benutzt. Und was heisst das genau 'korrekt benutzt'? >Sowas kann nur brauchbar funktionieren wenn A und B über ein definiertes >Protokoll miteinander kooperieren, alles andere wird Probleme geben. Das tun sie! Gruß Georg
Georg schrieb: >>Hmm, hmm, wer hat sich denn sowas ausgedacht? > > Ich, warum? Naja, weil es keine so gute Idee ist. Ich hätte auf eine Vorgabe von "oben" getippt... >>Schlägt fehl wenn B (in dem Moment) WM_CLOSE liest aber ignoriert oder >>als Reaktion eine Messagebox (Möchten Sie das Dokument speichern?) >>öffnet - vorzugsweise auf einem unerreichbaren Desktop. > > Kann nicht passieren, da Prozess B kein sichtbares Fenster hat - es > handelt sich um einen 'Worker-Prozess', wenn man das so sagen darf. Um eine Messagebox zu öffnen muss der Prozess kein eigenes Fenster haben, dank der Wunder von Windows. Im Zweifel ist es dann eine der beliebten "Wollen Sie den Prozess debuggen oder doch lieber killen?" Boxen. Sowas muss man aktiv unterdrücken, wird gern vergessen. >>Der Holzhammer ist TerminateProzess, korrekt benutzt. > > Und was heisst das genau 'korrekt benutzt'? Das hatte Uwe schon geschrieben. Plus TerminateProcess nimmt ein Handle auf den Prozess, nicht auf das Fenster (hat er nun eigentlich eins oder nicht? ;-). Plus alle möglichen Fehlerbehandlungen - keine Permissions für das Prozesshandle, Prozess gestorben zwischen Ermitteln des Handles und Versuch ihn zu killen, etc. pp. >>Sowas kann nur brauchbar funktionieren wenn A und B über ein definiertes >>Protokoll miteinander kooperieren, alles andere wird Probleme geben. > > Das tun sie! Laut Deiner Beschreibung nicht. WM_CLOSE oder gar TerminateProcess sind kein definiertes Protokoll, eine nutzerdefinierte Message, irgendwas mit benanntem Shared Memory oder benannte Events oder sowas (Stichwort IPC) wäre eins. D.h. man will ein für Programm A und B spezifisches(!) Protokoll, wo sich B auf Anfrage von A aktiv selber beendet. Und wenn B mehr als einmal laufen kann muss das explizit berücksichtigt werden.
Erstmal Danke für die vielen Antworten und Hinweise! Das was ich oben gepostet habe, ist bereits die Lösung, die ich momentan verwende (das 'Danke' ist etwas irreführend). Zunächst hatte ich immer nur PostMessage() ODER TerminateProcess() verwendet. Es ist aber entscheidend, eine KOMBINATION daraus zu nutzen (siehe oben). >Plus TerminateProcess nimmt ein Handle auf den Prozess, nicht auf das >Fenster (hat er nun eigentlich eins oder nicht? ;-). Ich programmiere am liebsten mit der WIN32 API. Und da wusste ich mir nicht anders zu helfen, als eine Anwendung mit Hauptfenster (CreateWindow()) zu erstellen, aber dann das Fenster nicht anzeigen zu lassen (ShowWindow(false)) - es gibt sicher elegantere Lösungen. >Laut Deiner Beschreibung nicht. WM_CLOSE oder gar TerminateProcess sind >kein definiertes Protokoll, eine nutzerdefinierte Message, irgendwas mit >benanntem Shared Memory oder benannte Events oder sowas (Stichwort IPC) >wäre eins. Den Prozess B gleich nach seinem Erstellen arbeiten zu lassen, und nach seinem gesteuerten Schließen (WM_CLOSE) nicht mehr arbeiten zu lassen, ist für mich durchaus ein definiertes Protokoll. Es lautet: Arbeite solange du am Leben bist! >Und wenn B mehr als einmal laufen kann muss das explizit berücksichtigt werden. B kann 'eigentlich' nur einmal laufen. Die Probleme treten nur auf, wenn mir der Prozess A abschmiert und eben den Prozess B nicht mehr sauber (WM_CLOSE) beenden kann. Das ist mir beim Debuggen aufgefallen. Und da jeder weiss (hier ist Windows ein beliebtes Beispiel!), dass bei Software immer mal etwas übersehen werden kann, wollte ich eben als 'Sicherheitsvorkehrung' meinen Prozess A beim Start dafür sorgen lassen, dass B nicht aktiv ist - also dass erstmal die Leichen aus dem Keller geholt werden. Gruß Georg
Ich finde das Konzept aber werkwürdig. Was passiert wenn sich mehre Nutzer gleichzeitig an dem PC anmelden? Dann kommen ein WM_CLOSE nicht von der einen Sitzung zur anderen. Also hat dann jeder der Benutzer auch diesen Prozess laufen, aber die Prozessliste ist dann abhängig davon ob du admin bist oder nicht. einmal sieht du den anderen BenutzerProzess einmal nicht. Das kann NIE sauber funktionieren. Wenn es wirklich genau einen Prozess auf dem PC geben soll, dann sollte man dafür einen Dienst schreiben. Dieser wird beim PC-Start mit gestartet und wenn abstützt wird er vom system neu gestartet.
>Was passiert wenn sich mehre Nutzer gleichzeitig an dem PC anmelden? Ehrlich gesagt habe ich darüber noch nicht nachgedacht - werde ich aber jetzt tun. >aber die Prozessliste ist dann abhängig davon ob du admin bist oder nicht. >einmal sieht du den anderen BenutzerProzess einmal nicht. Aber sobald ich ihn sehe kann ich ihn doch auch schließen (mit WM_CLOSE/TerminateProcess()), oder nicht? >Wenn es wirklich genau einen Prozess auf dem PC geben soll, dann sollte >man dafür einen Dienst schreiben. Aus Deiner Erklärung erschließt sich mir die Notwendigkeit eines Dienstes nicht, aber vlt. kenne ich mich dafür auch zu wenig aus.
Georg schrieb: [...] >>Laut Deiner Beschreibung nicht. WM_CLOSE oder gar TerminateProcess sind >>kein definiertes Protokoll, eine nutzerdefinierte Message, irgendwas mit >>benanntem Shared Memory oder benannte Events oder sowas (Stichwort IPC) >>wäre eins. > Den Prozess B gleich nach seinem Erstellen arbeiten zu lassen, und nach > seinem gesteuerten Schließen (WM_CLOSE) nicht mehr arbeiten zu lassen, > ist für mich durchaus ein definiertes Protokoll. Es lautet: > > Arbeite solange du am Leben bist! Hmm, ja, nein, naja, Grusel. Lies mal die Anmerkungen in der Doku zu TerminateProcess, z.B. unter <http://msdn.microsoft.com/en-us/library/ms686714%28v=VS.85%29.aspx>. Der Endzustand kann sehr wohl undefiniert sein, und es muss nichtmal zuverlässig funktionieren wenn sich irgendein asynchroner I/O nicht zeitnah abbrechen lässt. WM_CLOSE ist noch schlimmer weil der Prozess selber entscheiden kann ob er darauf überhaupt reagiert. >>Und wenn B mehr als einmal laufen kann muss das explizit berücksichtigt werden. > B kann 'eigentlich' nur einmal laufen. Das kann man auch halbwegs zuverlässig erzwingen, z.B. über benannte Semaphore. Ein Dienst (wie von Peter II geschrieben) löst das Problem auch, der kann per Definition nur einmal laufen und es gibt definierte APIs um den zu starten, zu stoppen und den Status abzufragen. Übrigens kannst Du nicht alles was Du sehen kannst (ich nehme mal an im Taskmanager und sowas) einfach schliessen/killen, ein modernes Windows hat auf so ziemlich jeden Shit Permissions an denen Du nicht einfach vorbeikommst. Man kann durchaus Dinge sehen/lesen dürfen die man aber nicht ändern/killen darf. Schöne neue Welt... ;-)
Hallo, >Lies mal die Anmerkungen in der Doku zu TerminateProcess, z.B. unter ><http://msdn.microsoft.com/en-us/library/ms686714%2.... >Der Endzustand kann sehr wohl undefiniert sein, und es muss nichtmal >zuverlässig funktionieren wenn sich irgendein asynchroner I/O nicht >zeitnah abbrechen lässt. Grob zusammengefasst: der Prozeß wird erst beendet, wenn alle abhängigen Kernel-Aktivitäten beendet wurden. Das wird vermutlich innerhalb einiger Millisekunden passiert sein. >WM_CLOSE ist noch schlimmer weil der Prozess selber entscheiden kann ob >er darauf überhaupt reagiert. Das ist dann natürlich schlecht. Aber mit der Definition einer eigenen Nachricht sollte ich das doch umgehen können. >Das kann man auch halbwegs zuverlässig erzwingen, z.B. über benannte >Semaphore. Kannst Du das evtl. noch etwas genauer erläutern? >Ein Dienst (wie von Peter II geschrieben) löst das Problem auch, der >kann per Definition nur einmal laufen und es gibt definierte APIs um den >zu starten, zu stoppen und den Status abzufragen. So ein Dienst ist mir etwas fremd - werde mich aber trotzdem mal damit beschäftigen. >Übrigens kannst Du nicht alles was Du sehen kannst (ich nehme mal an im >Taskmanager und sowas) einfach schliessen/killen... Naja, die genannten Prozesse wurden ja alle von mir bzw. dem aktuellen Nutzer erstellt. Da ich die Teile ja selber programmiere, sollte es doch irgendwie möglich sein eine Zugriffsverweigerung seitens Windows auszuschließen Gruß Georg
Georg schrieb: > Hallo, > >>Lies mal die Anmerkungen in der Doku zu TerminateProcess, z.B. unter >><http://msdn.microsoft.com/en-us/library/ms686714%2.... >>Der Endzustand kann sehr wohl undefiniert sein, und es muss nichtmal >>zuverlässig funktionieren wenn sich irgendein asynchroner I/O nicht >>zeitnah abbrechen lässt. > Grob zusammengefasst: der Prozeß wird erst beendet, wenn alle abhängigen > Kernel-Aktivitäten beendet wurden. Das wird vermutlich innerhalb einiger > Millisekunden passiert sein. Sollte man denken. Anekdote von vor vielen Jahren, nicht Windows sondern Solaris: das Killen eines Prozesses schlug fehl weil er gerade mit dem Tape-LW beschäftigt war (Rewind glaube ich), was wohl damals irgendwo im Kernel stattfand. So ein Tape war nicht so besonders schnell, wir warteten also viele, viele Minuten... Etwas näher an der heutigen Zeit: Netzwerk-Kram kann auch ziemlich lange dauern, etliche Dutzend Sekunden mit Retries. >>WM_CLOSE ist noch schlimmer weil der Prozess selber entscheiden kann ob >>er darauf überhaupt reagiert. > Das ist dann natürlich schlecht. Aber mit der Definition einer eigenen > Nachricht sollte ich das doch umgehen können. Dann hast Du ein spezielles Protokoll und die Prozesse kooperieren, also kann das ziemlich gut funktionieren. Das war ja der Punkt: man braucht ein extra Protokoll (ein vorhandenes einfach zu überladen führt potentiell zu Problemen) und die Prozesse müssen kooperieren. >>Das kann man auch halbwegs zuverlässig erzwingen, z.B. über benannte >>Semaphore. > Kannst Du das evtl. noch etwas genauer erläutern? Man kann in Windows allen moeglichen Systemobjekten (Semaphore, Mutexe, Events, usw.) systemweit sichtbare Namen geben. Damit kann man dann recht einfach zwischen kooperierenden Prozessen kommunizieren. >>Übrigens kannst Du nicht alles was Du sehen kannst (ich nehme mal an im >>Taskmanager und sowas) einfach schliessen/killen... > Naja, die genannten Prozesse wurden ja alle von mir bzw. dem aktuellen > Nutzer erstellt. Da ich die Teile ja selber programmiere, sollte es doch > irgendwie möglich sein eine Zugriffsverweigerung seitens Windows > auszuschließen OK, wenn die alle unter dem gleichen Account laufen ist das kein Problem. Auch wenn man sicher mit den ACLs perverse Konstellationen hinkriegen könnte, aber wer tut schon sowas.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.