Kann ich eine Strg-C (SIGINT) an eine Anwendung unter Windows senden?

89

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)?

Matthew Murdoch
quelle
1
Ich war daran interessiert, Strg-C an Java-Serviceprozesse zu senden, um Threaddumps zu erhalten. Es scheint, dass jstackstattdessen zuverlässig für diese spezielle Angelegenheit verwendet werden kann: stackoverflow.com/a/47723393/603516
Vadzim

Antworten:

30

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:

Nach langem Stöbern im Debugger stellte ich fest, dass der Einstiegspunkt, der das mit einem Signal wie Strg-Break verbundene Verhalten tatsächlich ausführt, kernel32! CtrlRoutine ist. Die Funktion hatte denselben Prototyp wie ThreadProc, sodass sie direkt mit CreateRemoteThread verwendet werden kann, ohne dass Code eingefügt werden muss. Dies ist jedoch kein exportiertes Symbol! Es hat unterschiedliche Adressen (und sogar unterschiedliche Namen) unter verschiedenen Windows-Versionen. Was ist zu tun?

Hier ist die Lösung, die ich mir endlich ausgedacht habe. Ich installiere einen Konsolen-Strg-Handler für meine App und generiere dann ein Strg-Unterbrechungssignal für meine App. Wenn mein Handler aufgerufen wird, schaue ich wieder oben im Stapel nach den Parametern, die an kernel32! BaseThreadStart übergeben wurden. Ich greife nach dem ersten Parameter, der die gewünschte Startadresse des Threads ist, nämlich der Adresse von kernel32! CtrlRoutine. Dann kehre ich von meinem Handler zurück und zeige an, dass ich das Signal verarbeitet habe und meine App nicht beendet werden sollte. Zurück im Hauptthread warte ich, bis die Adresse von kernel32! CtrlRoutine abgerufen wurde. Sobald ich es habe, erstelle ich im Zielprozess einen Remote-Thread mit der erkannten Startadresse. Dadurch werden die Strg-Handler im Zielprozess so ausgewertet, als ob Strg-Pause gedrückt worden wäre!

Das Schöne ist, dass nur der Zielprozess betroffen ist und jeder Prozess (auch ein Prozess mit Fenster) als Ziel ausgewählt werden kann. Ein Nachteil ist, dass meine kleine App nicht in einer Batch-Datei verwendet werden kann, da sie beim Senden des Ereignisses ctrl-break beendet wird, um die Adresse von kernel32! CtrlRoutine zu ermitteln.

(Stellen Sie vor, startwenn Sie es in einer Batch-Datei ausführen.)

arolson101
quelle
2
+1 - Der verknüpfte Code verwendet Strg-Umbruch anstelle von Strg-C, kann jedoch auf den ersten Blick (siehe Dokumentation zu GenerateConsoleCtrlEvent) für Strg-C angepasst werden.
Matthew Murdoch
8
Es gibt tatsächlich eine Funktion, die dies für Sie erledigt, lol, "GenerateConsoleCtrlEvent". Siehe: msdn.microsoft.com/en-us/library/ms683155(v=vs.85).aspx Siehe auch meine Antwort hier: serverfault.com/a/501045/10023
Triynko
1
Github Link im Zusammenhang mit der Antwort oben: github.com/walware/statet/tree/master/…
meawoppl
3
Es verwirrt den Verstand, dass Windows so alt ist wie es ist, und dennoch hat Microsoft keinen Mechanismus für Konsolenanwendung A bereitgestellt, um auf ein Signal von Konsolenanwendung B zu warten, damit Konsolenanwendung B Konsolenanwendung A anweisen kann, sauber herunterzufahren. Abgesehen von MS-Bashing habe ich auf jeden Fall SendSignal ausprobiert und "CreateRemoteThread fehlgeschlagen mit 0x00000005" erhalten. Irgendwelche anderen Ideen, wie man Anwendung A codiert, um auf ein Signal zu warten (jedes Signal, das bequem ist), und wie man es dann signalisiert?
David I. McIntosh
3
@ DavidI.McIntosh Es hört sich so an, als ob Sie in beiden Prozessen ein benanntes Ereignis erstellen möchten. Sie könnten dann voneinander signalisieren. Überprüfen Sie die Dokumentation für CreateEvent
arolson101
58

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:

  • Starten Sie ein Programm mit einem sichtbaren Fenster mit .Net, verstecken Sie sich mit Pinvoke, führen Sie es 6 Sekunden lang aus, zeigen Sie es mit Pinvoke an und stoppen Sie mit .Net.
  • Starten Sie ein Programm ohne Fenster mit .Net, führen Sie es 6 Sekunden lang aus, schließen Sie es an, indem Sie die Konsole anschließen und ConsoleCtrlEvent ausgeben

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.

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();

[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);

delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType);

// Enumerated type for the control messages sent to the handler routine
enum CtrlTypes : uint
{
  CTRL_C_EVENT = 0,
  CTRL_BREAK_EVENT,
  CTRL_CLOSE_EVENT,
  CTRL_LOGOFF_EVENT = 5,
  CTRL_SHUTDOWN_EVENT
}

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId);

public void StopProgram(Process proc)
{
  //This does not require the console window to be visible.
  if (AttachConsole((uint)proc.Id))
  {
    // Disable Ctrl-C handling for our program
    SetConsoleCtrlHandler(null, true); 
    GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);

    //Moved this command up on suggestion from Timothy Jannace (see comments below)
    FreeConsole();

    // Must wait here. If we don't and re-enable Ctrl-C
    // handling below too fast, we might terminate ourselves.
    proc.WaitForExit(2000);

    //Re-enable Ctrl-C handling or any subsequently started
    //programs will inherit the disabled state.
    SetConsoleCtrlHandler(null, false); 
  }
}

Planen Sie auch eine Notfalllösung ein, wenn AttachConsole()oder das gesendete Signal fehlschlägt, z. B. wenn Sie schlafen:

if (!proc.HasExited)
{
  try
  {
    proc.Kill();
  }
  catch (InvalidOperationException e){}
}
Stanislav
quelle
4
Inspiriert davon habe ich eine "eigenständige" cpp-App erstellt, die dies tut: gist.github.com/rdp/f51fb274d69c5c31b6be, falls es nützlich ist. Und ja, diese Methode kann anscheinend Strg + C oder Strg + Pause an "jede" PID senden.
Rogerdpack
Fehlender DLL-Import "SetConsoleCtrlHandler", aber das funktioniert.
Derf Skren
ausgezeichneter Beitrag. ausgezeichneter Blog. Ich würde vorschlagen, die StopProgramWithInvisibleWindowUsingPinvoke-Funktion in Ihrem Experimentierprogramm zu beenden. Ich hätte die Idee fast aufgegeben, weil ich dachte, Sie hätten keine Lösung gefunden
Wilmer Saint
Um dies zu vermeiden, habe 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.
56ka
FreeConsole sollte sofort nach dem Senden von GenerateConsoleCtrlEvent aufgerufen werden. Bis zum Aufruf wird Ihre Anwendung an die andere Konsole angehängt. Wenn die andere Konsole vor dem Schließen beendet wird, wird auch Ihre Anwendung beendet!
Timothy Jannace
17

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.

Shakta
quelle
6
Danke für die Lösung! Dies ist ein weiteres Beispiel dafür, dass die Windows-API so schrecklich durcheinander ist.
Vitaut
8

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 .

Reed Copsey
quelle
Ich möchte dies in einer Befehlszeilen-App (keine Fenster) tun. TerminateProcess ist ein Force-Kill-Mechanismus (ähnlich wie SIGKILL), sodass die terminierende Anwendung keine Möglichkeit zum Bereinigen bietet.
Matthew Murdoch
@Matthew Murdoch: Aktualisiert, um Informationen zur Handhabung in einer Konsolen-App aufzunehmen. Über denselben Mechanismus können Sie auch andere Ereignisse abfangen, z. B. das Herunterfahren von Fenstern oder das Schließen der Konsole usw. Ausführliche Informationen finden Sie unter MSDN.
Reed Copsey
@ Reed Copsey: Aber ich möchte dies von einem separaten Prozess aus initiieren. Ich habe mir GenerateConsoleCtrlEvent (von SetConsoleCtrlHandler referenziert) angesehen, aber dies scheint nur zu funktionieren, wenn sich der zu beendende Prozess in derselben 'Prozessgruppe' befindet wie der Prozess, der das Beenden ausführt ... Irgendwelche Ideen?
Matthew Murdoch
1
Matthew: Die einzige Idee, die ich hätte, wäre, den Prozess zu finden, das übergeordnete Element (die Konsole) zu finden, das Hauptfenster-Handle des übergeordneten Elements (die Konsole) abzurufen und mit SendKeys Strg + C direkt an ihn zu senden. Dies sollte dazu führen, dass Ihr Konsolenprozess CTRL_C_EVENT empfängt. Ich habe es aber nicht versucht - ich bin mir nicht sicher, wie gut es funktionieren würde.
Reed Copsey
Hier ist ein C ++ - Äquivalent zu SendKeys stackoverflow.com/questions/6838363/… siehe auch stackoverflow.com/questions/10407769/… obwohl es anscheinend auch dann nicht garantiert funktioniert ...
rogerdpack
7

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.

void SendControlC(int pid)
{
    AttachConsole(pid); // attach to process console
    SetConsoleCtrlHandler(NULL, TRUE); // disable Control+C handling for our app
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // generate Control+C event
}
KindDragon
quelle
und wie man die Kontrolle zurückgibt? und dann sende ich control-c, stopar programm, aber ich kann nichts mit seinen händen machen.
Jaroslaw L.
Wo kann man die Kontrolle zurückgeben?
KindDragon
Ich denke, Sie rufen SetConsoleCtrlHandler (NULL, FALSE) auf, um Ihren Handler zu entfernen. Weitere Informationen finden Sie in den verschiedenen anderen Antworten.
Rogerdpack
5

Hier ist der Code, den ich in meiner C ++ - App verwende.

Positive Punkte:

  • Funktioniert über die Konsolen-App
  • Funktioniert über den Windows-Dienst
  • Keine Verzögerung erforderlich
  • Schließt die aktuelle App nicht

Negative Punkte:

  • Die Hauptkonsole geht verloren und eine neue wird erstellt (siehe FreeConsole ).
  • Die Konsolenumschaltung liefert seltsame Ergebnisse ...

// Inspired from http://stackoverflow.com/a/15281070/1529139
// and http://stackoverflow.com/q/40059902/1529139
bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent)
{
    bool success = false;
    DWORD thisConsoleId = GetCurrentProcessId();
    // Leave current console if it exists
    // (otherwise AttachConsole will return ERROR_ACCESS_DENIED)
    bool consoleDetached = (FreeConsole() != FALSE);

    if (AttachConsole(dwProcessId) != FALSE)
    {
        // Add a fake Ctrl-C handler for avoid instant kill is this console
        // WARNING: do not revert it or current program will be also killed
        SetConsoleCtrlHandler(nullptr, true);
        success = (GenerateConsoleCtrlEvent(dwCtrlEvent, 0) != FALSE);
        FreeConsole();
    }

    if (consoleDetached)
    {
        // Create a new console if previous was deleted by OS
        if (AttachConsole(thisConsoleId) == FALSE)
        {
            int errorCode = GetLastError();
            if (errorCode == 31) // 31=ERROR_GEN_FAILURE
            {
                AllocConsole();
            }
        }
    }
    return success;
}

Anwendungsbeispiel:

DWORD dwProcessId = ...;
if (signalCtrl(dwProcessId, CTRL_C_EVENT))
{
    cout << "Signal sent" << endl;
}
56ka
quelle
4
        void SendSIGINT( HANDLE hProcess )
        {
            DWORD pid = GetProcessId(hProcess);
            FreeConsole();
            if (AttachConsole(pid))
            {
                // Disable Ctrl-C handling for our program
                SetConsoleCtrlHandler(NULL, true);

                GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // SIGINT

                //Re-enable Ctrl-C handling or any subsequently started
                //programs will inherit the disabled state.
                SetConsoleCtrlHandler(NULL, false);

                WaitForSingleObject(hProcess, 10000);
            }
        }
Тарик Ялауи
quelle
2

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:

(2014-3-7): Ich habe sowohl eine 32-Bit- als auch eine 64-Bit-Version mit Strg-C erstellt. Sie heißt SendSignalCtrlC.exe und kann unter folgender Adresse heruntergeladen werden: https://dl.dropboxusercontent.com/u/49065779/ sendignalctrlc / x86 / SendSignalCtrlC.exe https://dl.dropboxusercontent.com/u/49065779/sendsignalctrlc/x86_64/SendSignalCtrlC.exe - Juraj Michalak

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.

ioikka
quelle
2

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.

import com.sun.jna.platform.win32.Kernel32;    

public class CtrlCSender {

    public static void main(String args[]) {
        int processId = Integer.parseInt(args[0]);
        Kernel32.INSTANCE.AttachConsole(processId);
        Kernel32.INSTANCE.GenerateConsoleCtrlEvent(Kernel32.CTRL_C_EVENT, 0);
    }
}

Hauptanwendung - Führt CtrlCSender als separater Prozess consoless

ProcessBuilder pb = new ProcessBuilder();
pb.command("javaw", "-cp", System.getProperty("java.class.path", "."), CtrlCSender.class.getName(), processId);
pb.redirectErrorStream();
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
Process ctrlCProcess = pb.start();
ctrlCProcess.waitFor();
Patimo
quelle
hmm, wenn ich dies gegen einen Powershell-Prozess ausführe, bleibt der Prozess am Leben. Interessanterweise bringt das Ausführen von In-Process auf der JVM die VM tatsächlich zum Erliegen! Haben Sie eine Idee, warum ein Powershell-Prozess nicht auf diese Technik reagiert?
Groostav
2

Ja. Das windows-killProjekt macht genau das, was Sie wollen:

windows-kill -SIGINT 1234
BullyWiiPlaza
quelle
Dieses Projekt enthält gebrauchsfertige Release-Binärdateien zum Herunterladen hier: github.com/alirdn/windows-kill/releases - diese Antwort sollte mehr Upvote haben
boly38
0

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

Set WshShell = WScript.CreateObject("WScript.Shell")

WshShell.Run "notepad.exe"

WshShell.AppActivate "notepad"

WScript.Sleep 7000

WshShell.SendKeys "^C"
Frederic Simard
quelle
Dies funktioniert, wenn die Anwendung ein Fenster hat, das Sie AppActive (in den Vordergrund bringen) können.
Rogerdpack
0

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:

C:\>tasklist

So beenden Sie den Prozess:

C:\>Taskkill /IM firefox.exe /F
or
C:\>Taskkill /PID 26356 /F

Einzelheiten:

http://tweaks.com/windows/39559/kill-processes-from-command-prompt/

Awanish Kumar
quelle
Vermutlich sendet dies Sigterm?
Teknopaul
Taskkill sendet keine STRG-C. Überprüfen Sie die Windows-Signale.
Josi
0

Ich fand das alles zu kompliziert und verwendet Sendkeys eine senden CTRL- CTastendruck auf die Kommandozeilenfenster (dh cmd.exe Fenster) als Behelfslösung.

Thomiel
quelle
0
// Send [CTRL-C] to interrupt a batch file running in a Command Prompt window, even if the Command Prompt window is not visible,
// without bringing the Command Prompt window into focus.
// [CTRL-C] will have an effect on the batch file, but not on the Command Prompt  window itself -- in other words,
// [CTRL-C] will not have the same visible effect on a Command Prompt window that isn't running a batch file at the moment
// as bringing a Command Prompt window that isn't running a batch file into focus and pressing [CTRL-C] on the keyboard.
ulong ulProcessId = 0UL;
// hwC = Find Command Prompt window HWND
GetWindowThreadProcessId (hwC, (LPDWORD) &ulProcessId);
AttachConsole ((DWORD) ulProcessId);
SetConsoleCtrlHandler (NULL, TRUE);
GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0UL);
SetConsoleCtrlHandler (NULL, FALSE);
FreeConsole ();
user13669398
quelle