Pomimo faktu, że za pomocą GenerateConsoleCtrlEvent do wysyłania sygnału Ctrl + C jest prawidłowa odpowiedź to potrzebuje znaczącego wyjaśnień, aby działać w różny. Typy aplikacji NET.
Jeśli aplikacja .NET nie używa własną konsolę (WinForms/WPF/Windows życzenie/ASP.NET) podstawowy przepływ jest:
- Zamontuj główny proces .NET do konsoli procesu chcesz Ctrl + C
- Prevent główny proces .NET od zatrzymania z powodu zdarzenia Ctrl + C z SetConsoleCtrlHandler
- wygenerować zdarzenie na konsoli bieżącym konsoli z GenerateConsoleCtrlEvent (processGroupId powinna wynosić zero! Odpowiedź z kodem, który wysyła p.SessionId nie będzie działa i jest nieprawidłowy)
- Odłącz od konsoli i przywrócić Ctrl + C obsługi przez głównego procesu
Poniższy fragment kodu pokazuje, jak to zrobić:
Process p;
if (AttachConsole((uint)p.Id)) {
SetConsoleCtrlHandler(null, true);
try {
if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT,0))
return false;
p.WaitForExit();
} finally {
FreeConsole();
SetConsoleCtrlHandler(null, false);
}
return true;
}
gdzie SetConsoleCtrlHandler, FreeConsole, AttachConsole i GenerateConsoleCtrlEvent są natywne metody WinAPI:
internal const int CTRL_C_EVENT = 0;
[DllImport("kernel32.dll")]
internal static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
internal static extern bool FreeConsole();
[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);
// Delegate type to be used as the Handler Routine for SCCH
delegate Boolean ConsoleCtrlDelegate(uint CtrlType);
Rzeczy stają się bardziej złożone, jeśli trzeba wysłać Ctrl + C z aplikacji konsoli .NET. Podejście nie zadziała, ponieważ AttachConsole zwraca w tym przypadku wartość false (główna aplikacja konsoli ma już konsolę). Możliwe jest wywołanie FreeConsole przed wywołaniem AttachConsole, ale w rezultacie oryginalna konsola aplikacji .NET zostanie utracona, co w większości przypadków jest niedopuszczalne.
Moje rozwiązanie dla tego przypadku (to naprawdę działa i nie ma skutków ubocznych dla .NET konsoli głównego procesu):
- tworzyć małe program konsoli .NET wspieranie który akceptuje identyfikator procesu z argumentów wiersza poleceń, traci własna konsola z FreeConsole przed AttachConsole rozmowy i wysyła Ctrl + C, aby proces z kodem wspomniano powyżej
- procesu konsoli .NET Główny cel tylko wywołuje to narzędzie w nowym procesie, gdy jest konieczne do wysłania Ctrl + C do innego procesu konsoli
Pamiętaj, że działa tylko wtedy, gdy proces próbuje odczytać ze standardowego wejścia. Zamknięcie stdin nic nie robi, dopóki program nie spróbuje odczytać z niego czegoś. – Doug
dlaczego pokazuje ten wyjątek "StandardIn nie został przekierowany." ? Używam programu ffmpeg do przechwytywania ekranu. – Ahmad