CloseHandle ... Fehler meinerseits? Prozess lebt weiter



  • STARTUPINFO startUpInfo; 
    PROCESS_INFORMATION processInfo;
    [...]
    CreateProcess( NULL, name, NULL, NULL, FALSE, 0, NULL, NULL, &startUpInfo, &processInfo )
    [...]
    void ControlHandler(DWORD request) 
    {
    	int ok;
    
    	ok = 1;
        switch( request ) 
        { 
    		//Wenn der Service gestoppt wird:
            case SERVICE_CONTROL_STOP:
    			if( !CloseHandle( processInfo.hProcess ) )
    				ok = 0;
    			else if ( !CloseHandle( processInfo.hThread ) )
    				ok = 0;
    			if( 0 == ok )
    				WriteErrorToLog( GetLastError() );
    			else
    			{
    				WriteToLog( "Killing Process succeed." );
    
    				//In das Logfile eintragen, dass der Service beendet wurde.
    				WriteToLog( "Service stoped by Controlpanel\n\n" );
    
    				//Servicestatus zurücksetzen.
    				ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    				ServiceStatus.dwWin32ExitCode = 0;
    			}
            break; 
    
    		//Wenn der Computer heruntergefahren wird:
            case SERVICE_CONTROL_SHUTDOWN:
    			if( !CloseHandle( processInfo.hProcess ) )
    				ok = 0;
    			else if ( !CloseHandle( processInfo.hThread ) )
    				ok = 0;
    			if( 0 == ok )
    				WriteErrorToLog( GetLastError() );
    			else
    			{
    				WriteToLog( "Killing Process succeed." );
    
    				//In das Logfile eintragen, dass der Service beendet wurde.
    				WriteToLog( "Service stoped because Computer is shuting down.\n\n" );
    
    				//Servicestatus zurücksetzen.
    				ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    				ServiceStatus.dwWin32ExitCode = 0;
    			}
            break;
    
            default:
    		break;
        }
    
        //Den aktuellen Status setzen.
        SetServiceStatus (hStatus,  &ServiceStatus);
    }
    
    void WriteErrorToLog( int fehlerNachricht )
    {
    	char *fehler;
    	fehler = malloc( 1024 * sizeof(char) );
    
    	strcpy( fehler, "Es wurde ein Fehler mit dem Code: " );
    	strcat( fehler, intToChar( fehlerNachricht ) );
    	strcat( fehler, " gefunden." );
    
    	WriteToLog( fehler );
    }
    

    Ich wunderte mich dass er immer schrieb

    [Wed Jan 09 12:51:21 2008]: Service Started
    [Wed Jan 09 12:51:21 2008]: Try to start server...
    [Wed Jan 09 12:51:21 2008]: Wait for complete start:
    [Wed Jan 09 12:51:21 2008]: Complete start successfull.
    [Wed Jan 09 12:51:21 2008]: Service works.
    [Wed Jan 09 12:51:26 2008]: Killing Process succeed.
    [Wed Jan 09 12:51:26 2008]: Service stoped by Controlpanel
    

    denn der Prozess lief immer weiter 😮

    Dann habe ich mal einfach so schreiben lassen (also den Fehler-Code)

    [Wed Jan 09 13:04:52 2008]: Service Started
    [Wed Jan 09 13:04:52 2008]: Try to start server...
    [Wed Jan 09 13:04:52 2008]: Wait for complete start:
    [Wed Jan 09 13:04:52 2008]: Complete start successfull.
    [Wed Jan 09 13:04:52 2008]: Service works.
    [Wed Jan 09 13:04:56 2008]: Es wurde ein Fehler mit dem Code: 0 gefunden.
    [Wed Jan 09 13:04:56 2008]: Service stoped by Controlpanel
    

    Wieso klappt alles, und der Prozess läuft weiter?

    MFG Oli



  • Weil CloseHandle gar nicht die Aufgabe hat, den Prozess hinter dem übergebenem Handle zu beenden - es gibt nur das Handle frei, mit dem du auf diesen Prozess verwiesen hast. Um den Prozess zu beenden, mußt du ihm schon mitteilen, daß Feierabend ist (z.B. über SendMessage())*, und anschließend darauf warten, daß er sich wirklich beendet hat.

    * Wenn du sehr verzweifelt bist, kannst du auch die Haubitze "TerminateProcess()" auspacken - aber die ist nur für absolute Notfälle vorgesehen.



  • Also

    SendMessage( OpenProcess( 0, FALSE, (DWORD)processInfo.hProcess ),  );
    

    Was kommt dann? Wo kann ich diese Nachrichten finden, die ih übergeben kann?

    *PC_Neustart_DA 100%_CPU_LAST_WEGEN_UNKILLED_PROCESSES* << hehe



  • Wenn du das Programm am anderen Ende selber geschrieben hast, kannst du auch eine eigene Nachricht definieren (über RegisterWindowMessage()), die du versenden kannst. Wenn das Zielprogramm fertig vorgegeben ist, würde ich es mit Standardnachrichten wie WM_CLOSE versuchen.



  • SendMessage( OpenProcess( 0, FALSE, (DWORD)processInfo.hProcess ), WM_CLOSE, 0, 0 );
    

    😕 mit WM_QUIT hats nicht geklappt.



  • SendMessage erwartet ein Fensterhandle, OpenProcess gibt aber nur ein Prozesshandle zurück. Die Kombination von beiden funktioniert generell nicht.



  • Und wie mache ich dass dann?


  • Mod

    Wenn Du statt CreateProcess, ShellExecuteEx verwendest, dann bekommst Du das Fensterhandle frei Haus.

    EDIT: Die sist nicht korrekt. ShelleExecuteEx liefert kein Fenster-Handle des neuen Prozesses zurück!



  • Könnte ShellExecuteEx dann auch Fenster anzeigen?



  • Martin Richter schrieb:

    Wenn Du statt CreateProcess, ShellExecuteEx verwendest, dann bekommst Du das Fensterhandle frei Haus.

    Huch, wie denn das? Das hwnd in SHELLEXECUTEINFO ist doch nur als Elternfenster für eventuelle Fehlerhinweise gedacht.



  • myProcess.cbSize = sizeof( SHELLEXECUTEINFO );
    	myProcess.fMask = SEE_MASK_DOENVSUBST;
    	myProcess.hwnd = NULL;
    	myProcess.lpVerb = tmp;
    	myProcess.lpFile = pName;
    	myProcess.lpParameters = NULL;
    	myProcess.lpDirectory = path;
    	myProcess.nShow = SW_MAXIMIZE;
    	myProcess.hInstApp = seErr;
    	myProcess.lpIDList = 0;
    	myProcess.lpClass = NULL;
    	myProcess.hkeyClass = NULL;
    	myProcess.dwHotKey = 0;
    	//myProcess.DUMMYUNIONNAME.hIcon = NULL;
    	//myProcess.DUMMYUNIONNAME.hMonitor = SEE_MASK_HMONITOR;
    	myProcess.hProcess = NULL;
    
    	ShellExecuteEX( myProcess );
    
    void ControlHandler(DWORD request) 
    {
    	int ok;
    
    	LPDWORD tmp;
    
    	ok = 1;
        switch( request ) 
        { 
    		//Wenn der Service gestoppt wird:
            case SERVICE_CONTROL_STOP:
    			//SendMessage( OpenProcess( 0, FALSE, (DWORD)processInfo.hProcess ), WM_CLOSE, 0, 0 );
    
    			GetExitCodeThread( processInfo.hThread, tmp );
    			ExitThread( *tmp );
    
    			GetExitCodeProcess( processInfo.hProcess, tmp );
    			ExitProcess( *tmp );
    
    			WriteToLog( "Killing Process succeed." );
    
    			//In das Logfile eintragen, dass der Service beendet wurde.
    			WriteToLog( "Service stoped by Controlpanel\n\n" );
    
    			//Servicestatus zurücksetzen.
    			ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    			ServiceStatus.dwWin32ExitCode = 0;
            break;
    

    ganz ehrlich? Ich glaube dass ist Falsch.

    Ich habe bei sowas immer ein ungutes gefühl 🙄

    Ich habe den Rest des Codes noch nicht umgebaut, wollte erst mal wissen wass ihr dazu sagt!?

    [eidt]Code erneuert
    [edit2] neuer code( Geht dass auch so, mit CreateProcess? Der Service stürzt beim Beenden ab... )


  • Mod

    sri schrieb:

    Martin Richter schrieb:

    Wenn Du statt CreateProcess, ShellExecuteEx verwendest, dann bekommst Du das Fensterhandle frei Haus.

    Huch, wie denn das? Das hwnd in SHELLEXECUTEINFO ist doch nur als Elternfenster für eventuelle Fehlerhinweise gedacht.

    Upps. Sorry! Habe mich vertan...



  • Könnt ihr mir da noch mal Helfen?

    Wie kann ich denn einen Prozess von CreateProcess beenden?
    Geht dass mit meinem geschriebenen

    GetExitCodeThread( processInfo.hThread, tmp );
                ExitThread( *tmp );
    
                GetExitCodeProcess( processInfo.hProcess, tmp );
                ExitProcess( *tmp );
    

    Code?



  • ExitThread() und ExitProcess() beenden deinen eigenen Thread bzw. Prozess, damit dürfte dir nicht geholfen sein. Du müsstest das Hauptfenster des geöffneten Prozesses finden (ist aber nicht gerade einfach, zumal nicht jeder Prozess ein Hauptfenster haben muß) und eine WM_CLOSE Nachricht dorthin schicken. Wenn das aufgerufene Programm vernünftig ist, beendet es sich als Reaktion darauf.
    (eventuell könnte auch PostThreadMessage() helfen)

    PS: Was für ein Programm willst du überhaupt auf diese Weise steuern? Ein eigenes oder etwas fertig gegebenes?



  • Ich will lediglich eine *.exe die meine 2 Azubi-Kollegen geschrieben haben starten und dann beenden.

    Sie schreiben dass Programm, ich den passenden Dienst quasi.
    Werde mal "PostThreadMessage" anschauen.

    [edit]
    Soll ich einfach

    PostThreadMessage( processInfo.hTread, WM_CLOSE, 0, 0 )
    

    ich kann mit den letzten beiden nichts anfangen....
    Was sind das für Parameter?

    [edit2]

    if( !PostThreadMessage( (DWORD)processInfo.hThread, WM_CLOSE, 0, 0 ) )
    				WriteErrorToLog( GetLastError() );
    			else
    			{
    				WriteToLog( "Killing Process succeed." );
    
    				//In das Logfile eintragen, dass der Service beendet wurde.
    				WriteToLog( "Service stoped by Controlpanel\n\n" );
    
    				//Servicestatus zurücksetzen.
    				ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    				ServiceStatus.dwWin32ExitCode = 0;
    			}
    

    Geschrieben wird:

    [Thu Jan 10 14:07:32 2008]: Service Started
    [Thu Jan 10 14:07:32 2008]: Try to start server...
    [Thu Jan 10 14:07:32 2008]: Wait for complete start:
    [Thu Jan 10 14:07:32 2008]: Complete start successfull.
    [Thu Jan 10 14:07:32 2008]: Service works.
    [Thu Jan 10 14:07:35 2008]: Es wurde ein Fehler mit dem Code: 1444 gefunden.
    [Thu Jan 10 14:07:35 2008]: Killing Process succeed.
    [Thu Jan 10 14:07:35 2008]: Service stoped by Controlpanel
    

    1444 = Invalid Thread ID 😮 😮 😕



  • void ControlHandler(DWORD request) 
    {
    	int ok;
    
    	LPDWORD tmp;
    
    	ok = 1;
        switch( request ) 
        { 
    		//Wenn der Service gestoppt wird:
            case SERVICE_CONTROL_STOP:
    
    			if( !PostThreadMessage( processInfo.dwThreadId, WM_QUIT, 0, 0 ) )
    				WriteErrorToLog( GetLastError() );
    			else
    			{
    				WriteToLog( "Killing Process succeed." );
    
    				//In das Logfile eintragen, dass der Service beendet wurde.
    				WriteToLog( "Service stoped by Controlpanel\n\n" );
    
    				//Servicestatus zurücksetzen.
    				ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    				ServiceStatus.dwWin32ExitCode = 0;
    			}
            break; 
    
    		//Wenn der Computer heruntergefahren wird:
            case SERVICE_CONTROL_SHUTDOWN:
    			if( !PostThreadMessage( processInfo.dwThreadId, WM_QUIT, 0, 0 ) )
    				WriteErrorToLog( GetLastError() );
    			else
    			{
    				WriteToLog( "Killing Process succeed." );
    
    				//In das Logfile eintragen, dass der Service beendet wurde.
    				WriteToLog( "Service stoped because Computer is shuting down.\n\n" );
    
    				//Servicestatus zurücksetzen.
    				ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    				ServiceStatus.dwWin32ExitCode = 0;
    			}
            break;
    
            default:
    		break;
        }
    
        //Den aktuellen Status setzen.
        SetServiceStatus (hStatus,  &ServiceStatus);
    }
    

    So sieht dass aus, und ins log kommt dass:

    [Thu Jan 10 14:22:27 2008]: Service Started
    [Thu Jan 10 14:22:27 2008]: Try to start server...
    [Thu Jan 10 14:22:27 2008]: Wait for complete start:
    [Thu Jan 10 14:22:27 2008]: Complete start successfull.
    [Thu Jan 10 14:22:27 2008]: Service works.
    [Thu Jan 10 14:22:39 2008]: Killing Process succeed.
    [Thu Jan 10 14:22:39 2008]: Service stoped by Controlpanel
    

    Aber leider läuft der Prozess weiter...

    Muss ich in der *.exe Datei dess Prozesses irgendwas machen, das dass klappt?



  • Eventuell wäre es erstmal eine gute Idee, deinen Erfolg zu überprüfen, bevor du die Bestätigung rausschreibst (WaitForSingleObject() könnte helfen). Und dann muß das Zielprogramm immer noch auf deine Message reagieren - und dazu brauchst du dessen Mithilfe.

    Edit: Hast du den letzten Code auch mal mit WM_CLOSE ausprobiert?


  • Mod



  • Ja ich habe WM_CLOSE auch ausprobiert, allerdings ohne die Erolgsabfrage..

    Martin Richter schrieb:

    Ich kann es nicht mehr sehen:

    Super...
    Also:
    Du hast schon öfter geantwortet, dafür bin ich dankbar, aber ich Zitiere mal deinen Schulss vom Post

    Martin Richter schrieb:

    Der richtige Weg ist und bleibt es das/alle Main Window(s) zu zerstören und entsprechend dann (im WM_DESTROY Handler) PostQuitMessage (AfxPostQuitMessage) auszuführen.

    Super, was meinst du mit "(im WM_DESTROY Handler)"...
    Ich bin nicht sooo der gieg im C-Programmieren,
    könntest du dass nochmal ausführen,
    evtl mit psoydo -schreibt man dass so?- Code.

    Ich erwarte von dir KEINEN fertigen Code, bitte, ich will ja auch irgendwo lernen 😉 ⚠

    Eventuell nochmal ein part zur kreation dess Prozesses:

    if( CreateProcess( NULL, name, NULL, NULL, FALSE, 0, NULL, NULL, &startUpInfo, &processInfo ) )
    	{
    		WriteToLog( "Wait for complete start:" );
    
    		WriteToLog( "Complete start successfull." );
    	}
    	else
    	{
    		WriteErrorToLog( GetLastError() );
    		error = 1;
    	}
    

    Also weis ichnicht was du mit Fenster meinst oder so....





  • Interessant bestimmt, aber nur in C++,
    ich programmiere C


Anmelden zum Antworten