Я могу отправить ctrl-C (SIGINT) в приложение в Windows?

добавить ссылку в метатеге <meta name="theme-color" content="red">

82
задан JasonMArcher 18 May 2015 в 17:23
поделиться

3 ответа

Ближе всего к решению я пришел к SendSignal стороннему приложению. Автор перечисляет исходный код и исполняемый файл. Я проверил, что он работает в 64-битных окнах (работает как 32-битная программа, убивая другую 32-битную программу), но я не понял, как встроить код в программу Windows (либо 32-битную программу). или 64-бит).

Как это работает:

После долгих поисков в отладчике я обнаружил, что точкой входа, которая фактически выполняет поведение, связанное с сигналом, подобным ctrl-break, является kernel32! CtrlRoutine. У функции был тот же прототип, что и у ThreadProc, поэтому ее можно было использовать с CreateRemoteThread напрямую, без необходимости вводить код. Однако это не экспортированный символ! Он находится по разным адресам (и даже имеет разные названия) в разных версиях Windows. Что делать?

Вот решение, которое я наконец придумал. Я устанавливаю консольный обработчик ctrl для своего приложения, а затем генерирую сигнал ctrl-break для своего приложения. Когда вызывается мой обработчик, я смотрю на верхнюю часть стека, чтобы узнать параметры, переданные в kernel32! BaseThreadStart. Я беру первый параметр, который является желаемым начальным адресом потока, который является адресом kernel32! CtrlRoutine. Затем я возвращаюсь из обработчика, указывая, что я обработал сигнал и мое приложение не должно завершаться. Вернувшись в основной поток, я жду, пока не будет получен адрес kernel32! CtrlRoutine. Получив его, я создаю удаленный поток в целевом процессе с обнаруженным начальным адресом. Это заставляет обработчики ctrl в целевом процессе оцениваться, как если бы была нажата ctrl-break!

Приятно то, что затрагивается только целевой процесс, и любой процесс (даже оконный) может быть целевым. Одним из недостатков является то, что мое маленькое приложение нельзя использовать в пакетном файле, так как оно убьет его, когда отправит событие ctrl-break, чтобы узнать адрес kernel32! CtrlRoutine.

(предшествует ] start , если запускается в пакетном файле.)

27
ответ дан 24 November 2019 в 09:18
поделиться

Редактировать:

Для приложения с графическим интерфейсом «нормальным» способом решения этой проблемы при разработке Windows будет отправка сообщения WM_CLOSE в главное окно процесса.

Для консоли приложению, вам нужно использовать SetConsoleCtrlHandler , чтобы добавить CTRL_C_EVENT .

Если приложение этого не соблюдает, вы можете вызвать TerminateProcess .

7
ответ дан 24 November 2019 в 09:18
поделиться

Думаю, я немного опоздал с этим вопросом, но я все равно напишу что-нибудь для тех, у кого такая же проблема. Это тот же ответ, что я дал на этот вопрос .

Моя проблема заключалась в том, что я хотел бы, чтобы мое приложение было приложением с графическим интерфейсом, но выполняемые процессы должны выполняться в фоновом режиме без прикрепленного окна интерактивной консоли. Я думаю, что это решение также должно работать, когда родительский процесс является консольным. Возможно, вам придется удалить флаг «CREATE_NO_WINDOW».

Мне удалось решить эту проблему с помощью GenerateConsoleCtrlEvent () с приложением-оболочкой. Сложность заключается в том, что в документации не совсем ясно, как именно ее можно использовать и какие подводные камни с ней связаны.

Мое решение основано на том, что описано здесь . Но это тоже не объясняет всех деталей и с ошибкой, поэтому вот подробности о том, как заставить его работать.

Создайте новое вспомогательное приложение «Helper.exe». Это приложение будет находиться между вашим приложением (родительским) и дочерним процессом, который вы хотите закрыть. Это также создаст фактический дочерний процесс. У вас должен быть этот процесс «среднего человека», иначе функция GenerateConsoleCtrlEvent () завершится ошибкой.

Используйте какой-то механизм IPC, чтобы сообщить родительскому процессу вспомогательному процессу, что вспомогательный процесс должен закрыть дочерний процесс. Когда помощник получает это событие, он вызывает «GenerateConsoleCtrlEvent (CTRL_BREAK, 0)», который закрывает себя и дочерний процесс. Я сам использовал для этого объект события, который родитель завершает, когда хочет отменить дочерний процесс.

Чтобы создать Helper.exe, создайте его с помощью CREATE_NO_WINDOW и CREATE_NEW_PROCESS_GROUP. И при создании дочернего процесса создайте его без флагов (0), что означает, что он будет выводить консоль от своего родителя. В противном случае он проигнорирует событие.

Очень важно, чтобы каждый шаг выполнялся таким образом. Я пробовал всевозможные комбинации, но эта комбинация - единственная, которая работает. Вы не можете отправить событие CTRL_C. Он вернет успех, но будет проигнорирован процессом. CTRL_BREAK - единственный, который работает. На самом деле это не имеет значения, поскольку в конце они оба вызовут ExitProcess ().

Вы также не можете вызвать GenerateConsoleCtrlEvent () с идентификатором группы процессов для идентификатора дочернего процесса, напрямую позволяя вспомогательному процессу продолжать работу. Это тоже не удастся.

Я потратил целый день, пытаясь заставить это работать. Это решение работает для меня, но если у кого-то есть что добавить, сделайте это. Я поискал в сети множество людей с похожими проблемами, но не нашел однозначного решения проблемы. Как работает GenerateConsoleCtrlEvent (), тоже немного странно, поэтому, если кто-нибудь знает о нем более подробную информацию, поделитесь.

17
ответ дан 24 November 2019 в 09:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: