Ich habe (in der Vergangenheit) geschrieben Cross-Plattform (Windows / Unix) Anwendungen , die, wenn sie von der Kommandozeile gestartet, einen benutzer getippt behandelt Ctrl- CKombination in der gleichen Art und Weise (dh die Anwendung sauber zu beenden).
Ist es unter Windows möglich, ein Ctrl- C/ SIGINT / Äquivalent zu einem Prozess von einem anderen (nicht verwandten) Prozess zu senden, um eine saubere Beendigung anzufordern (wodurch die Möglichkeit besteht, Ressourcen usw. aufzuräumen)?
jstack
stattdessen zuverlässig für diese spezielle Angelegenheit verwendet werden kann: stackoverflow.com/a/47723393/603516Antworten:
Am nächsten an einer Lösung ist die SendSignal- App eines Drittanbieters. Der Autor listet den Quellcode und eine ausführbare Datei auf. Ich habe überprüft, ob es unter 64-Bit-Fenstern funktioniert (als 32-Bit-Programm ausgeführt, ein anderes 32-Bit-Programm beendet), aber ich habe nicht herausgefunden, wie der Code in ein Windows-Programm eingebettet werden kann (entweder 32-Bit) oder 64-Bit).
Wie es funktioniert:
(Stellen Sie vor,
start
wenn Sie es in einer Batch-Datei ausführen.)quelle
Ich habe einige Nachforschungen zu diesem Thema angestellt, die sich als beliebter herausstellten, als ich erwartet hatte. Die Antwort von KindDragon war einer der entscheidenden Punkte.
Ich habe einen längeren Blog-Beitrag zu diesem Thema geschrieben und ein funktionierendes Demo-Programm erstellt, das die Verwendung dieses Systemtyps zum Schließen einer Befehlszeilenanwendung auf ein paar nette Arten demonstriert. Dieser Beitrag listet auch externe Links auf, die ich in meiner Forschung verwendet habe.
Kurz gesagt, diese Demo-Programme bieten Folgendes:
Bearbeiten: Die geänderte Lösung von KindDragon für diejenigen, die sich hier und jetzt für den Code interessieren. Wenn Sie nach dem Stoppen des ersten Programms andere Programme starten möchten, sollten Sie die Strg-C-Behandlung erneut aktivieren. Andernfalls erbt der nächste Prozess den deaktivierten Status des übergeordneten Elements und reagiert nicht auf Strg-C.
Planen Sie auch eine Notfalllösung ein, wenn
AttachConsole()
oder das gesendete Signal fehlschlägt, z. B. wenn Sie schlafen:quelle
wait()
ich Strg-C (SetConsoleCtrlHandler(null, false);
) erneut aktiviert . Ich habe einige Tests durchgeführt (mehrere Anrufe, auch bei bereits beendeten Prozessen) und (noch?) Keine Nebenwirkung festgestellt.Ich denke, ich bin etwas spät dran, aber ich werde trotzdem etwas für jeden schreiben, der das gleiche Problem hat. Dies ist die gleiche Antwort, die ich auf diese Frage gegeben habe.
Mein Problem war, dass meine Anwendung eine GUI-Anwendung sein soll, die ausgeführten Prozesse jedoch im Hintergrund ausgeführt werden sollten, ohne dass ein interaktives Konsolenfenster angehängt ist. Ich denke, diese Lösung sollte auch funktionieren, wenn der übergeordnete Prozess ein Konsolenprozess ist. Möglicherweise müssen Sie jedoch das Flag "CREATE_NO_WINDOW" entfernen.
Ich habe es geschafft, dies mit GenerateConsoleCtrlEvent () mit einer Wrapper-App zu lösen . Der schwierige Teil ist nur, dass die Dokumentation nicht wirklich klar ist, wie sie genau verwendet werden kann und welche Gefahren damit verbunden sind.
Meine Lösung ist auf das, was beschrieben wird hier . Aber das hat auch nicht wirklich alle Details und mit einem Fehler erklärt. Hier sind die Details, wie man es zum Laufen bringt.
Erstellen Sie eine neue Hilfsanwendung "Helper.exe". Diese Anwendung befindet sich zwischen Ihrer Anwendung (übergeordnet) und dem untergeordneten Prozess, den Sie schließen möchten. Außerdem wird der eigentliche untergeordnete Prozess erstellt. Sie müssen diesen "Middle Man" -Prozess haben, sonst schlägt GenerateConsoleCtrlEvent () fehl.
Verwenden Sie einen IPC-Mechanismus, um vom übergeordneten zum Hilfsprozess zu kommunizieren, dass der Helfer den untergeordneten Prozess schließen soll. Wenn der Helfer dieses Ereignis erhält, ruft er "GenerateConsoleCtrlEvent (CTRL_BREAK, 0)" auf, wodurch er selbst und der untergeordnete Prozess geschlossen werden. Ich habe selbst ein Ereignisobjekt verwendet, das der Elternteil abschließt, wenn er den untergeordneten Prozess abbrechen möchte.
Um Ihre Helper.exe zu erstellen, erstellen Sie sie mit CREATE_NO_WINDOW und CREATE_NEW_PROCESS_GROUP. Wenn Sie den untergeordneten Prozess erstellen, erstellen Sie ihn ohne Flags (0), was bedeutet, dass die Konsole von ihrem übergeordneten Prozess abgeleitet wird. Andernfalls wird das Ereignis ignoriert.
Es ist sehr wichtig, dass jeder Schritt so ausgeführt wird. Ich habe alle Arten von Kombinationen ausprobiert, aber diese Kombination ist die einzige, die funktioniert. Sie können kein CTRL_C-Ereignis senden. Es wird Erfolg zurückgeben, aber vom Prozess ignoriert. CTRL_BREAK ist die einzige, die funktioniert. Das spielt keine Rolle, da beide am Ende ExitProcess () aufrufen.
Sie können GenerateConsoleCtrlEvent () auch nicht mit einer Prozessgruppen-ID der untergeordneten Prozess-ID aufrufen, damit der Hilfsprozess weiterleben kann. Dies wird ebenfalls fehlschlagen.
Ich habe einen ganzen Tag damit verbracht, dies zum Laufen zu bringen. Diese Lösung funktioniert für mich, aber wenn jemand noch etwas hinzuzufügen hat, tun Sie dies bitte. Ich ging durch das Internet und fand viele Leute mit ähnlichen Problemen, aber ohne endgültige Lösung des Problems. Die Funktionsweise von GenerateConsoleCtrlEvent () ist ebenfalls etwas seltsam. Wenn jemand weitere Details dazu kennt, teilen Sie diese bitte mit.
quelle
Bearbeiten:
Für eine GUI-App besteht die "normale" Möglichkeit, dies in der Windows-Entwicklung zu handhaben, darin, eine WM_CLOSE-Nachricht an das Hauptfenster des Prozesses zu senden.
Für eine Konsolen-App müssen Sie SetConsoleCtrlHandler verwenden , um eine hinzuzufügen
CTRL_C_EVENT
.Wenn die Anwendung dies nicht berücksichtigt, können Sie TerminateProcess aufrufen .
quelle
Gibt irgendwie einen
GenerateConsoleCtrlEvent()
Fehler zurück, wenn Sie ihn für einen anderen Prozess aufrufen, aber Sie können eine Verbindung zu einer anderen Konsolenanwendung herstellen und ein Ereignis an alle untergeordneten Prozesse senden.quelle
Hier ist der Code, den ich in meiner C ++ - App verwende.
Positive Punkte:
Negative Punkte:
Anwendungsbeispiel:
quelle
quelle
Es sollte kristallklar gemacht werden, weil es im Moment nicht ist. Es gibt eine modifizierte und kompilierte Version von SendSignal zum Senden von Strg-C (standardmäßig wird nur Strg + Pause gesendet). Hier sind einige Binärdateien:
Ich habe diese Dateien auch für den Fall gespiegelt:
32-Bit-Version: https://www.dropbox.com/s/r96jxglhkm4sjz2/SendSignalCtrlC.exe?dl=0
64-Bit-Version: https://www.dropbox.com /s/hhe0io7mcgcle1c/SendSignalCtrlC64.exe?dl=0
Haftungsausschluss: Ich habe diese Dateien nicht erstellt. An den kompilierten Originaldateien wurden keine Änderungen vorgenommen. Die einzige getestete Plattform ist das 64-Bit-Windows 7. Es wird empfohlen, die unter http://www.latenighthacking.com/projects/2003/sendSignal/ verfügbare Quelle anzupassen und selbst zu kompilieren.
quelle
In Java wird JNA mit der Kernel32.dll-Bibliothek verwendet, ähnlich einer C ++ - Lösung. Führt die CtrlCSender-Hauptmethode als Prozess aus, bei dem nur die Konsole des Prozesses das Strg + C-Ereignis an das Ereignis sendet und das Ereignis generiert. Da es separat ohne Konsole ausgeführt wird, muss das Strg + C-Ereignis nicht deaktiviert und erneut aktiviert werden.
CtrlCSender.java - Basierend auf den Antworten von Nemo1024 und KindDragon .
Bei einer bekannten Prozess-ID hängt diese konsolose Anwendung die Konsole des Zielprozesses an und generiert darauf ein STRG + C-Ereignis.
Hauptanwendung - Führt CtrlCSender als separater Prozess consoless
quelle
Ja. Das
windows-kill
Projekt macht genau das, was Sie wollen:quelle
Ein Freund von mir schlug eine völlig andere Art der Lösung des Problems vor und es funktionierte für mich. Verwenden Sie ein vbscript wie unten. Es beginnt und Anwendung, lassen Sie es für 7 Sekunden laufen und schließen es mit Strg + c .
'VBScript Beispiel
quelle
Basierend auf der Prozess-ID können wir das Signal an den Prozess senden, um es gewaltsam oder ordnungsgemäß zu beenden, oder an jedes andere Signal.
Alle Prozesse auflisten:
So beenden Sie den Prozess:
Einzelheiten:
http://tweaks.com/windows/39559/kill-processes-from-command-prompt/
quelle
Ich fand das alles zu kompliziert und verwendet Sendkeys eine senden CTRL- CTastendruck auf die Kommandozeilenfenster (dh cmd.exe Fenster) als Behelfslösung.
quelle
quelle