Gestartetes externes Programm wieder beenden
-
Hallo,
mit CreateProcess() habe ich ein externes Programm gestartet:
static char *cmdline = "C:\\Test.exe"; static LPSTARTUPINFO info = new STARTUPINFO; pinfo = new PROCESS_INFORMATION; info->lpReserved = NULL; info->cbReserved2 = 0; info->lpReserved2 = NULL; info->lpDesktop = NULL; info->lpTitle = cmdline; info->dwXSize = 800; info->dwYSize = 600; info->hStdOutput = cout; info->dwFlags = STARTF_USESIZE & STARTF_USESTDHANDLES; if (!CreateProcess(NULL, cmdline, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, info, pinfo)) { Fehler(); } else { Geklappt(); }
... waa alles prima funktioniert.
Über folgenden Code wollte ich das Programm wieder beenden:PostMessage(pinfo->hProcess, WM_CLOSE, 0, 0); CloseHandle( pinfo->hProcess ); delete pinfo; pinfo = NULL;
... was leider ignoriert wird.
Hat einer eine Idee, wo mein Denkfehler liegt?Vielen Dank
Gruß Bernhard
-
Hallo Bernhard,
du mußt mit PostMessage WM_CLOSE an das Window Handle schicken und nicht an das Prozess Handle.
MfG Stephan
-
Und um deine nächste Frage auch gleich zu beantworten: es gibt keine Funktion mit der man das "main window" eines Prozesses ermitteln kann.
Was man machen kann ist alle Top-Level Fenster mit EnumWindows() zu enumerieren, und dann mit GetWindowThreadProcessID() die Prozess-ID ermitteln (aber Achtung, Prozess-ID != Prozess-Handle!).
Dann hast du mal ne Liste von Top-Level Fenstern des Prozesses. Die einfachste Variante ist dann an alle ein WM_CLOSE zu posten.Das funktioniert ganz "OK" mit grafischen Anwendungen. Bei Konsolenapplikationen sollte man vermutlich anders vorgehen.
-
Es gibt sons noch einen Befehl TerminateProcess mit diesem lassen sich bequem Prozesse beenden.
Kann dir sonst am Abend noch eine Fixfertige Prozedur posten.
//HIER DER SOURCE
//*************************************************************************** //Name: KillProcess // //Funktion: Beendet einen Prozess // //Beschreibung: Beendet einen Prozess abrubt // //Parameter: DWORD: ID des Prozesses // //Rückgabewert: - //*************************************************************************** void __fastcall ThreadProcessReader::KillProcess(DWORD dwProcessID) { HANDLE hProcess; DWORD dwExitCode; if (dwProcessID > 0) { //Query vorbereiten hProcess = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, false, dwProcessID); if (hProcess) { //Prozess beenden GetExitCodeProcess(hProcess, &dwExitCode); TerminateProcess(hProcess, dwExitCode); } CloseHandle(hProcess); } }
-
Es gibt übrigens keinen Grund,
STARTUPINFO
undPROCESS_INFORMATION
auf dem Heap zu erzeugen. Es sei denn, das Erzeugen von Speicherlecks gehört zu dem gewünschten Verhalten deines Programms. Leg´ die Variablen einfach auf dem Stack an und übergib´ deren Adresse an denCreateProcess
Aufruf.
Außerdem musst du die beiden HandleshProcess
undhThread
mitCloseHandle
schließen, wenn derCreateProcess
Aufruf erfolgreich war, andernfalls entsteht ein Ressourcenleck.