Это выглядит невыполнимой задачей. Абсолютно ничего из того, что я нашел, не работает. Вопрос в том, как чисто закрыть консольное приложение, запущенное с Process.Start, которое было запущено без окна консоли и без использования оболочки execute: (ProcessStartInfo.CreateNoWindow = true; ProcessStartInfo.UseShellExecute = false;
).
Предполагается, что запускаемое приложение завершит работу «чисто», если получит сигнал ctrl-c или ctrl-break, но, похоже, нет способа отправить ему тот, который работает (особенно GenerateConsoleCtrlEvent).
- Process.Kill не работает. Он оставляет поврежденные файлы из-за внезапного прекращения работы процесса.
- Process.CloseMainWindow не работает. В этом случае нет главного окна, поэтому функция возвращает false и ничего не делает.
- Вызов EnumThreadWindows во всех потоках процесса и отправка WM_CLOSE в каждое окно ничего не делает, и в любом случае окон потоков нет.
- GenerateConsoleCtrlEvent не работает. Это полезно только для процессов в одной и той же группе (которую .NET не дает вам контролировать), с нежелательным побочным эффектом закрытия вызывающего процесса в любом случае. Функция не позволяет указывать идентификатор процесса.
Тот, кто может предоставить код, который принимает объект «Процесс», запущенный с указанными выше параметрами, что приводит к полному завершению работы запущенного процесса, не затрагивая вызывающий процесс, будет отмечен как ответ. Используйте 7z.exe (архиватор 7-zip) в качестве примера консольного приложения, которое начинает сжимать большой файл и оставляет поврежденный незавершенный файл, если его не завершить полностью.
Пока кто-то не предоставит функциональный пример или код, который приводит к функциональному примеру, на этот вопрос нет ответа. Я видел десятки людей, задающих этот вопрос и десятки ответов в Интернете, и ни один из них не работал. .NET, похоже, не поддерживает полное закрытие консольного приложения с учетом его идентификатора процесса, что странно, учитывая, что оно запущено с помощью объекта .NET Process. Частично проблема заключается в невозможности создать процесс в новой группе процессов, что делает использование GenerateConsoleCtrlEvent бесполезным. У этого должно быть решение.
GenerateConsoleCtrlEvent
. Итак, вам просто нужно выяснить, как создать процесс в новой группе. Если это невозможно с помощью оболочки процесса .NET, перейдите к собственной функции Win32. Нет вреда в использовании P / Invoke, вы все равно делаете это дляGenerateConsoleCtrlEvent
. - person Cody Gray   schedule 22.04.2013unsafe
, чего я не делаю. Другая проблема с CreateProcess заключается в том, что я не могу надежно использовать Process.EnableRaisingEvents и событие Exited, потому что процесс может завершиться до того, как я получу возможность вызвать Process.GetProcessById для создания экземпляра процесса .NET для назначения обработчика, который обычно сделано перед вызовом Process.Start. Меня заставляют переписывать большую часть логики Win32. - person Triynko   schedule 22.04.2013unsafe
блоков кода. Вы можете сделать это в VB.NET, который не поддерживает необработанные указатели. Просто немного больше проблем. Вы должны использовать методы классаMarshal
. Я понятия не имею, почему еще вы бы избегали использования P / Invoke, это просто кажется нелогичным. Да, чтобы получить доступ к мощи Win32, вам нужно проделать намного больше работы. Нет идеальной обертки. Это одна из причин, почему я вернулся к C ++ и Win32 после изучения C #. - person Cody Gray   schedule 23.04.2013GenerateConsoleCtrlEvent
не работает. К сожалению, сейчас у меня нет времени тестировать ваш пример кода. - person Cody Gray   schedule 23.04.2013