Fremden Prozess beenden!



  • Hi.

    Mein Ziel ist es einen fremden Prozess so zu beenden, als hätte der Benutzer den Process selbst beendet. Es ist wichtig, dass der fremde Prozess ganz normal beendet wird, da er sonst nicht alle gesammelten Informationen abspeichert.

    Ich verwende folgende Funktion, um den Process zu beenden:

    (nach der CreateRemoteThread-Anleitung auf http://www.edgeofnowhere.cc/viewtopic.php?p=2483118)

    void __fastcall TerminateApp(DWORD pid)
    {
      LPVOID LoadLibAddy;
      HANDLE hWnd = OpenProcess(PROCESS_ALL_ACCESS,false, pi.dwProcessId);
      if (hWnd == 0) ShowMessage("Cannot open process!");
      LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "ExitProcess");
      if (LoadLibAddy == 0) ShowMessage("GetProcAddress failed!");
      if(!CreateRemoteThread(hWnd, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)0, NULL, NULL)) ShowMessage("CreateRemoteThread failed!");
    }
    //---------------------------------------------------------------------------
    

    Das Problem ist, dass der Prozess so beendet wird als hätte ich TerminateProcess verwendet. Wende ich den Code z.B. auf MS Word an, kommt nicht die Nachfarge, ob ich meine Arbeit speichern möchte. Der Prozess wird einfach beendet.

    Hat hier jemand einen Alternativvorschlag?
    Mit SendMessage(hWnd, WM_QUIT,0,0) habe ich es leider nicht hinbekommen.

    Ich freue mich schon auf weitere Ideen 😃


  • Mod

    Das ist ja auch ein Holzhammer. Sende einfach WM_CLOSE per PostMessage/SendMessage je nachdem wie Du synchronisieren willst.



  • Danke für die Antwort. Diesen Weg

    if (!PostMessage(FindWindow("ZSNESWIN",0), WM_CLOSE,0,0)) ShowMessage("PostMessage failed");
    

    habe ich auch schon ausprobiert. Der Prozess läuft weiter aber die GUI wird wenigstens geschlossen^^.

    Ich habe nochmal folgenden Quellcode verwendet, um alle zum Prozess gehörenden Fenster zu schließen (von http://support.microsoft.com/default.aspx?scid=KB;en-us;178893&):

    BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;
    
    DWORD __fastcall TerminateApp2( DWORD dwPID, DWORD dwTimeout )
       {
    	  HANDLE   hProc ;
    	  DWORD   dwRet ;
    
    	  // If we can't open the process with PROCESS_TERMINATE rights,
    	  // then we give up immediately.
    	  hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
    		 dwPID);
    
    	  if(hProc == NULL)
    	  {
    		ShowMessage("Cannot open process!");
    	  }
    
    	  // TerminateAppEnum() posts WM_CLOSE to all windows whose PID
    	  // matches your process's.
    	  EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;
    
    	  // Wait on the handle. If it signals, great. If it times out,
    	  // then you kill it.
    	  if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
    		 ShowMessage("Process needs to be killed the hard way");
    	  else
    		 ShowMessage("Process was cleanly terminated");
    
    	  CloseHandle(hProc) ;
    
    	  return dwRet ;
       }
    
    //---------------------------------------------------------------------------
    BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam )
       {
          DWORD dwID ;
    
    	  GetWindowThreadProcessId(hwnd, &dwID) ;
    
    	  if(dwID == (DWORD)lParam)
    	  {
    		 PostMessage(hwnd, WM_CLOSE, 0, 0) ;
    	  }
    
    	  return TRUE ;
       }
    

    Die Fenster werden alle wunderbar geschlossen. Auch die Informationen, die gespeichert werden sollen, werden gespeichert. Der einzige Hacken ist, dass der Prozess auch ohne Fenster weiterläuft, sowie die Spielmusik weiterhin zu hören ist. Da jedoch alle Informationen gespeichert wurden, kann man ihn ja an dieser Stelle mit TerminateProcess beenden^^.
    Gibt es für diese Methode noch Verbesserungsmöglichkeiten? Wenn ich auf das X klicke, bzw ALT+F4 drücke wird der Prozess ja "richtig" und "vollständig" beendet.



  • Da habe ich mich wohl zu früh gefreut 😞
    Die Informationen werden doch nicht gespeichert 😞
    Es muss also noch einen anderen weg geben, um ein Programm zu beenden.



  • Mit einem Snapshot kannst du durch die Prozesse gehen, und bekommst dann den Handle mit OpenProcess, die du für TerminateProcess brauchst.

    Pseudo-Code:

    hSnapshot = CreateToolhelp32Snapshot();
    Process32First(hSnapshot, &pe);
    
    while(Process32Next(hSnapshot, &pe) != ERROR_NO_MORE_FILES)
    {
       hProcess = OpenProcess(pe.th32ProcessId);
       TerminateProcess(hProcess);
    }
    


  • Das Handle ist ja nicht das Problem. Der fremde Prozess wird ja von mir mit CreateProcess erstellt. TerminateProcess funktioniert leider zu gut. Der Prozess soll aber beendet werden als hätte ich auf das X (schließen) geklickt, da sonst von dem Prozess gesammelte Informationen verloren gehen.

    Wie würde der Befehl für SendMessage lauten, um dem Fenster die Message ALT+F4 zu schicken. Mit keybd_event funktioniert es leider nicht nicht.

    Vielleicht ist es für euch nochmal hilfreich zu wissen, dass es sich um eine Art Frontend handelt. Der fremde Prozess wir von meinem Programm gestartet und soll dann duch eine Tastenkombinatino wieder beendet werden (nur nicht mit TerminateProcess).


  • Mod

    Mapp schrieb:

    Danke für die Antwort. Diesen Weg

    if (!PostMessage(FindWindow("ZSNESWIN",0), WM_CLOSE,0,0)) ShowMessage("PostMessage failed");
    

    habe ich auch schon ausprobiert. Der Prozess läuft weiter aber die GUI wird wenigstens geschlossen^^.

    Logo! Du findest ja auch das Fenster nicht! Und dann sendest Du an NULL!
    Sorge erstmal dafür das fenster zu finden... Dann sende WM_CLOSE!

    Wenn Du möchtest, dass Daten gespeichert werden ist WM_CLOSE der einzige Ansatz!



  • @ Martin Richter
    Du hast recht. Der Befehl sollte

    PostMessage(FindWindow(0,"ZSNESWIN"), WM_CLOSE,0,0)
    

    lauten.

    Dann wird das Fenster auch geschlossen. Mit TerminateApp2 sollten auch alle vestcken Fenster geschlossen werden. Ich frage mich nur, wieso die Exe weiterlaüft, obwohl an alle Fenster WM_CLOSE geschickt wurde.

    Wie kann man per SendMessage ALT+F4 emulieren?

    Danke.



  • Um Alt+F4 zu emulieren, scheint man mit

    SendMessage(hwnd,WM_SYSCOMMAND,0x0000f060,0);
    

    weiter zu kommen. Wie schon erwähnt, wird dann dass Fenster gesclossen aber die Anwendung läuft weiter.
    Bei der Anwendung handelt sich um eine DirectX Anwendung. Ich nehme an, dass wenn man das Fenster per Maus schließt, noch weitere Befehle ausgeführt werden, die mir nicht zugänglich sind.

    Hat noch jemand eine Idee?


Anmelden zum Antworten