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 und PROCESS_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 den CreateProcess Aufruf.
    Außerdem musst du die beiden Handles hProcess und hThread mit CloseHandle schließen, wenn der CreateProcess Aufruf erfolgreich war, andernfalls entsteht ein Ressourcenleck.


Anmelden zum Antworten