Chyba trochę się spóźniłem z tym pytaniem, ale i tak napiszę coś dla każdego, kto ma ten sam problem. To ta sama odpowiedź, jaką udzieliłem na to pytanie.
Mój problem polegał na tym, że chciałbym, aby moja aplikacja była aplikacją GUI, ale wykonywane procesy powinny być uruchamiane w tle bez dołączonego interaktywnego okna konsoli. Myślę, że to rozwiązanie powinno również działać, gdy proces nadrzędny jest procesem konsoli. Może być jednak konieczne usunięcie flagi „CREATE_NO_WINDOW”.
Udało mi się to rozwiązać za pomocą GenerateConsoleCtrlEvent () z aplikacją opakowującą. Najtrudniejsze jest po prostu to, że dokumentacja nie jest do końca jasna, jak można go używać i jakie są z nim pułapki.
Moje rozwiązanie opiera się na tym, co opisano tutaj . Ale to też nie wyjaśniło wszystkich szczegółów i zawiera błąd, więc oto szczegóły, jak to działa.
Utwórz nową aplikację pomocniczą „Helper.exe”. Ta aplikacja będzie znajdować się między Twoją aplikacją (rodzicem) a procesem podrzędnym, który chcesz zamknąć. Stworzy również rzeczywisty proces potomny. Musisz mieć ten proces "pośrednika" lub GenerateConsoleCtrlEvent () nie powiedzie się.
Użyj pewnego rodzaju mechanizmu IPC, aby przekazać od rodzica do procesu pomocniczego, że osoba pomagająca powinna zamknąć proces potomny. Gdy pomocnik otrzyma to zdarzenie, wywołuje „GenerateConsoleCtrlEvent (CTRL_BREAK, 0)”, co zamyka siebie i proces potomny. Użyłem do tego obiektu zdarzenia, który rodzic wykonuje, gdy chce anulować proces potomny.
Aby utworzyć plik Helper.exe, utwórz go za pomocą CREATE_NO_WINDOW i CREATE_NEW_PROCESS_GROUP. Tworząc proces potomny, stwórz go bez flag (0), co oznacza, że uzyska konsolę od swojego rodzica. Niezastosowanie się do tego spowoduje zignorowanie zdarzenia.
Bardzo ważne jest, aby każdy krok był wykonywany w ten sposób. Próbowałem różnych kombinacji, ale ta kombinacja jest jedyną, która działa. Nie możesz wysłać zdarzenia CTRL_C. Zwróci sukces, ale zostanie zignorowany przez proces. CTRL_BREAK jest jedynym, który działa. Nie ma to większego znaczenia, ponieważ w końcu oboje wywołają ExitProcess ().
Nie można również wywołać GenerateConsoleCtrlEvent () z identyfikatorem grupy procesów będącym identyfikatorem procesu potomnego, co pozwala bezpośrednio procesowi pomocniczemu na kontynuowanie życia. To również się nie powiedzie.
Spędziłem cały dzień, starając się, aby to zadziałało. U mnie to rozwiązanie działa, ale jeśli ktoś ma coś jeszcze do dodania, zrób to. Przeszukałem całą sieć, znajdując wiele osób z podobnymi problemami, ale bez konkretnego rozwiązania problemu. Sposób działania GenerateConsoleCtrlEvent () jest również trochę dziwny, więc jeśli ktoś zna więcej szczegółów na ten temat, udostępnij.
jstack
zamiast tego można niezawodnie wykorzystać w tej konkretnej sprawie: stackoverflow.com/a/47723393/603516