Hartnäckigen Prozess beenden



  • Hallo

    Ich habe eine Gamer-Mouse mit 10 Tasten; um diese mit Funktionen zu belegen, muss die Software des Herstellers installiert werden (Saitek).
    Problem ist: Die Software besteht aus mehreren einzelnen Programmen; der Loader für diese einzelnen Programme hängt sich anscheinend irgendwann unbemerkt auf. Das äussert sich darin, das sich Windows (Vista 32 bit HP) nicht runterfahren lässt bzw das runterfahren 2 Minuten dauert, weil halt dieser Prozess das verhindert. Das Problem schilderten auch andere im Saitek-Forum; aber die können das nicht nachvollziehen.

    Ich habe jetzt quasi einen Loader für den Loader geschrieben; d.h. mein Loader startet den Saitek-Loader als Prozess:

    stInfo.dwFlags=STARTF_USESHOWWINDOW;
     stInfo.wShowWindow=SW_HIDE;
    started = CreateProcess(NULL, 
                             "ProfilerU.exe", 
                             NULL, 
                             NULL, 
                             TRUE,
                              BELOW_NORMAL_PRIORITY_CLASS,
                             NULL,
                             NULL,
                             &stInfo, 
                             &prInfo);
     nRetValue = nError = GetLastError();
    

    Ich fange die Nachricht "OnEndSession" in meinem Programm ab, und versuche die Saitek-Software mit:

    BOOL result;
    result=::TerminateProcess(prInfo.hProcess,(UINT)lpExitCode);
    

    ...abzuschießen. Das klappt aber leider nicht. Im moment in meiner Testversion lasse ich mir das Ergebnis anzeigen:

    if(!result) MessageBox("Profiler erfolgreich beendet!",0,0);
    else  MessageBox("Profiler lässt sich nicht beenden!",0,0);
    

    Meist dauert es dann diese 2 Minuten, bis ich die negative Nachricht bekomme, das sich der Prozess nicht beenden lässt.

    Nun ist halt die Frage: Gibt es noch was aggresiveres als TerminateProcess, oder kann ich das noch anders initialisieren? Habe auch schon "taskkill" versucht, leider auch ohne Erfolg.



  • Ich würde eher meinen, dass OnEndSession zuerst an den Prozess vom Loader des Herstellers geschickt wird (weil wahrscheinlich erst später gestartet) und auf eine Antwort gewartet wird und anschließend erst OnEndSession an deinen Prozess gesendet wird. Versuch doch mal ne MessageBox an den Anfang von deinem Handler für OnEndSession zu setzen und guck mal, wann dieser denn nun eigentlich aufgerufen wird.

    PS: Forum wäre wohl eher WinAPI



  • Dieser Thread wurde von Moderator/in Unix-Tom aus dem Forum MFC (Visual C++) in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hi

    ...das ist tatsächlich so...
    Verd.... Wie kann ich das jetzt am geschicktesten angehen?



  • Es gibt eine brutale Lösung: Mit FindWindow hwndProc des abzuschiessenden Prozesses holen, dann SendMessage(hwndProc,WM_DESTROY,0,0) abschicken. Solltest Du ausprobieren - ist aber nicht das Gelbe vom Ei.



  • berniebutt schrieb:

    Es gibt eine brutale Lösung: Mit FindWindow hwndProc des abzuschiessenden Prozesses holen, dann SendMessage(hwndProc,WM_DESTROY,0,0) abschicken.

    Das bringt ihm doch nichts, sein Handler wird doch gar nicht rechtzeitig aufgerufen um den Prozess zu beenden. Und außerdem bezweifle ich, dass dieser Loader-Prozess ein Fenster hat - geschweige denn dass er sich durch das Schließen des Fensters beenden ließe.



  • HI

    Schon seltsam. Dachte eigentlich, das mein Prozess zuerst die Nachricht zum beenden erhält. Im Taskmanager sieht man das nicht, aber im ProzessExplorer läuft halt der ProfilerU.exe unter meinem.

    Kann ich das vielleicht unterbinden, z.B. indem ich den Prozess anders aufrufe?

    Und nein, der Saitek-Loader hat kein Fenster.



  • Hi

    Sorry für den Doppelpost, aber ich kann meinen ersten nicht editieren.

    Da ich ein Handle auf den aufgerufenen Prozess habe, kann ich dann nicht dessen Nachrichten abfangen?



  • Deimos schrieb:

    Da ich ein Handle auf den aufgerufenen Prozess habe, kann ich dann nicht dessen Nachrichten abfangen?

    Selbst dann könnte es ja sein, dass der Prozess zuerst auf die Nachricht reagiert und blockiert.

    Du könntest vllt. zuerst den Loader-Prozess starten und danach den eigenen Prozess forken - der Parent beendet und das Kind läuft weiter.


  • Mod

    Wenn TerminateProcess versagt gehe ich davon aus, dass eine interne Struktur des Prozesses blockiert wird die auch das Ausführen von TerminateProcess verhindert.
    IMHO hast Du da gar keine Chance, weil es nicht mal mehr dem OS möglich ist den Prozess zu beenden.



  • Martin Richter schrieb:

    Wenn TerminateProcess versagt gehe ich davon aus, dass eine interne Struktur des Prozesses blockiert wird die auch das Ausführen von TerminateProcess verhindert.
    IMHO hast Du da gar keine Chance, weil es nicht mal mehr dem OS möglich ist den Prozess zu beenden.

    (OT: Interessanterweise passiert das auf meinem Notebook recht häufig, nachdem es aus dem Standby-Modus oder dem Ruhezustand wieder aufgewacht ist. Ich vermute die Schuld bei irgendeiner Anwendung, die einen systemweiten Hook installiert, der mit Treibern kommuniziert (Touchpad, Fingerprint-Reader, Präsentationsmanager o.ä.). Aber wie debuggt man sowas?)



  • Hallo

    Ja, das wäre Plan B: Den Fehler finden und bereinigen. Das wird aber nicht einfacher.

    Was anderes: Wenn das tatsächlich so ist, das die Prozesse, die als letztes gestartet werden, als erstes beendet werden, dann könnte ich ja noch versuchen nach dem Loader quasi einen Quitter zu starten, dem ich irgendwie das Handle zu dem Saitek-Prozess übergebe. Den Loader kann ich dann ja beenden.

    Ich habe auch schon versucht, auf die Maus Zugriff zu bekommen, um die Software nachzubauen. Ich bekomme die Tasten aber net rein. Aus dem ProzessExplorer weiß ich, das die ne DX-dll geladen haben. Also werden die wohl über den DInput kommunizieren. Aber wie gesagt, ich bekomm nix rein (DX8-SDK).



  • Martin Richter schrieb:

    IMHO hast Du da gar keine Chance, weil es nicht mal mehr dem OS möglich ist den Prozess zu beenden.

    Wie darf ich mir das denn vorstellen? Immerhin ist in letzter Instanz doch der Scheduler des OS dafür verantwortlich, welcher Prozess wann laufen darf. Der wird doch wohl in der Lage sein, den Prozess rauszuwerfen? Oder übersehe ich da gerade etwas?



  • ich kann mir dies nicht vorstellen. wenn es so ist, wie devkid sagt, können sie den prozess dann nicht unerminieren und die entsprechende Fenster Prozedur aushebeln, um so die WM_QUERYENDSESSION direkt abzufangen, so dass die wahre Fenster Prozedur sie nie erhalten wird!?



  • Hallo

    Ich werd´ das heute mal basteln: Nach dem Saitek-loader starte ich noch einen "Quitter"; ist das tatsächlich so, dann müsste der zuerst aufgerufen werden.

    Ich habe zur Kontrolle in den Loader ne Messagebox gemacht, die mir den Aufruf von OnEndSession meldet. Die kommt tatsächlich erst nach den genannten 2 Minuten; und direkt danach kommt die Meldung "...kann nicht beendet werden". Sehr warscheinlich, weil der Prozess dann schon nicht mehr läuft.

    Es gibt ja auch nen Schlüssel in der Registry, "Waittokillprocess" oder so ähnlich. Den hab´ ich auf 3 sekunden. Bringt aba nix.



  • mad_martin schrieb:

    Wie darf ich mir das denn vorstellen? Immerhin ist in letzter Instanz doch der Scheduler des OS dafür verantwortlich, welcher Prozess wann laufen darf. Der wird doch wohl in der Lage sein, den Prozess rauszuwerfen? Oder übersehe ich da gerade etwas?

    Das ist schon möglich. Wenn unter Linux beispielsweise ein Prozess als "Zombie" markiert ist, kann der Prozess auch nicht gekillt werden, da dadurch eventuell Resourcen im Nichts verschwinden würden.

    @Deimos: Das war auch bloß eine Idee, es kann auch sein, dass sich der Prozess trotzdem nicht richtig abschießen lassen lässt.



  • Hallo

    Also TerminateProcess scheint doch zu funktionieren. D.h. ich habe in meinen Loader nun einen Button, mit dem ich per TerminateProcess den Saitek-Loader abschießen kann. Das hat jetzt auch seit ich das benutze sehr gut funktioniert.

    Leider kann ich anscheinend das Handle nicht an den Quitter übergeben. Dachte, ich lös das ganz billig, indem ich das Handle speichere:

    CStdioFile file;
    CString string;
    string.Format("%d\n%d\n%d\n%d",prInfo.dwProcessId,prInfo.dwThreadId,prInfo.hProcess,prInfo.hThread);
    
    file.Open("D:\\Handle.txt",CStdioFile::modeCreate|CStdioFile::modeReadWrite,0);
    
    file.WriteString(string);
    file.Close();
    

    und in dem Quitter wieder öffne:

    if(file.Open("D:\\Handle.txt",CStdioFile::modeRead))
    {
    file.ReadString(string);
    value=atoi(string.GetBuffer());
    
    prInfo.dwProcessId=value;
    
    file.ReadString(string);
    value=atoi(string.GetBuffer());
    
    prInfo.dwThreadId=value;
    
    file.ReadString(string);
    value=atoi(string.GetBuffer());
    
    prInfo.hProcess=(HANDLE)value;
    
    file.ReadString(string);
    value=atoi(string.GetBuffer());
    
    prInfo.hThread=(HANDLE)value;
    
    file.Close();
    

    Funzt aba net. Die Variablen stimmen, aber das Handle funktioniert nicht; d.h. ich kann nicht auf den vorher aufgerufenen Saitek-Loader zugreifen.

    Geht das überhaupt irgendwie?



  • Hi

    ...Selbstantwort:

    handle=OpenProcess(PROCESS_ALL_ACCESS,0,value1);
    

Log in to reply