Forum: PC-Programmierung Prozess beenden


von Georg (Gast)


Lesenswert?

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

von Georg (Gast)


Lesenswert?

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!

von Christopher (Gast)


Lesenswert?

Ohne C zu kennen würde ich sagen du musst vorher überprüfen ob der 
Prozess überhaupt vorhanden ist

von Uwe (Gast)


Lesenswert?

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.

von Jasch (Gast)


Lesenswert?

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.

von Georg (Gast)


Lesenswert?

>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

von Jasch (Gast)


Lesenswert?

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.

von Georg (Gast)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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.

von Georg (Gast)


Lesenswert?

>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.

von Jasch (Gast)


Lesenswert?

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

von Georg (Gast)


Lesenswert?

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

von Jasch (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.