Отправка произвольного сигнала в Windows?
Linux поддерживает отправку произвольного Posix-сигнала, такого как SIGINT
или SIGTERM
, в процесс с помощью kill
-Command. В то время как SIGINT
и SIGTERM
являются просто скучными старыми способами прекращения процесса в дружественном или не-дружественном виде, SIGQUIT
предназначен для запуска дампа ядра. Это можно использовать для запуска запущенной виртуальной машины Java для печати дампа потока, включая стек стеков всех работающих потоков - аккуратно! После печати информации об отладке Java VM продолжит делать то, что было раньше; на самом деле свалка потока происходит только в другом порожденном потоке с максимальным приоритетом. (Вы можете попробовать это самостоятельно, используя kill -3 <VM-PID>
.)
Обратите внимание, что вы также можете регистрировать свои собственные обработчики сигналов с помощью классов (неподдерживаемых!) Signal
и SignalHandler
в sun.misc
-пакете, поэтому вы можете иметь с ним всевозможные удовольствия.
Однако мне еще предстоит найти способ отправки сигнала в процесс Windows. Сигналы создаются с помощью определенных пользовательских входов: Ctrl-C
запускает a SIGINT
на обеих платформах, например. Но, похоже, нет никакой утилиты для ручного отправки сигнала на запущенный, но неинтерактивный процесс в Windows. Очевидным решением является использование исполняемого файла Cygwin kill
, но, хотя он может завершать процессы Windows с использованием соответствующего Windows API, я не мог отправить с ним SIGBREAK
(эквивалент Windows SIGQUIT
); на самом деле я думаю, что единственным сигналом, который он может отправить на процессы Windows, является SIGTERM
.
Итак, чтобы сделать длинный рассказ коротким и повторить заголовок: Как отправить произвольный сигнал процессу в Windows?
Ответы
Ответ 1
Если вы хотите явно/программно убить другую программу/процесс любого типа, в pstools SysInternals есть небольшой инструмент с именем "pskill", который ведет себя так же, как и Unixen "kill".
Если вы хотите что-то еще, продолжайте читать (хотя я могу ошибаться в некоторых из нижеприведенных спецификаций - это были эоны, так как я в последний раз разрабатывал программу Windows на C, используя только WinAPI и Charles Petzold превосходные книги "Программирование для Windows", как руководство).
В Windows у вас нет должным образом "сигналов", какие функции WinMain и WinProc получают из операционной системы - это простые сообщения. Например, когда вы нажимаете кнопку "X" в окне, Windows отправляет обработчику Windows сообщение WM_CLOSE. Когда окно удаляется, но программа все еще работает, он отправляет WM_DESTROY. Когда он собирается выйти из основного цикла обработки сообщений, WinMain (не WinProc) получает WM_QUIT. Ваша программа должна реагировать на все это, как и ожидалось, - вы можете фактически разработать "незамкнутое" приложение, не делая того, что должно было получить при получении WM_CLOSE.
Когда пользователь выбирает задачу из диспетчера задач Windows и нажимает "Завершить задачу", ОС отправит WM_CLOSE (и другую, которую я не помню). Если вы используете "Конечный процесс", процесс уничтожается напрямую, сообщения не отправляются (источник: The Old New Thing
Я помню, что был способ получить окно HWND другого процесса, как только вы получите, что другой процесс может отправить этому окну сообщение через функции PostMessage и DispatchMessage.
Ответ 2
Windows не является POSIX. Он не имеет сигналов. Единственные "сигналы", которые получают консольные программы, это если они вызывают SetConsoleCtrlHandler
, и в этом случае он может быть уведомлен о том, что пользователь нажал Ctrl + C, Ctrl + Break, закрыл окно консоли, вышел из системы или закрыл систему.
Все остальное сделано с помощью IPC, как правило, с помощью оконных сообщений или RPC. Проверьте документацию Sun, чтобы узнать, есть ли способ сделать то, что вы просите в Windows JRE.
Ответ 3
В Windows все вращается вокруг сообщений Win32. Я не верю, что для этого есть инструмент командной строки, но на С++ вы можете использовать FindWindow для отправки произвольного сообщения в другую программу Windows, например:.
#define WM_MYMSG ( WM_USER+0x100 )
HWND h = ::FindWindow(NULL,_T("Win32App"));
if (h) {
::PostMessage(h, WM_MYMSG, 0, 0);
}
Это также можно сделать в С# с помощью com interop.
Ответ 4
Вы также можете использовать jconsole для просмотра stacktrace всех запущенных потоков. Это будет работать в Windows и любой другой ОС, поддерживающей Java. jconsole также имеет много других приятных функций, графиков памяти, графиков процессора и т.д.
Он не отвечает на ваш первоначальный вопрос, но, надеюсь, позволяет получить те же результаты.
Если вы не знакомы с jconsole, ознакомьтесь с документацией Using JConsole.
Ответ 5
Мне просто интересно, есть ли PsTools, теперь принадлежащая Microsoft, SysInternals поможет вам.
Ответ 6
Ruby каким-то образом может (хотя бы эмулировать) SIGINT SIGKILL и т.д. на окнах и ловить эти сообщения. Можете проверить это.
Как ruby "посылает сигнал SIGINT в этот процесс" внизу, в окнах, на самом деле должен вызывать TerminateProcess
или эквивалент на этом PID.
Также есть эквивалентный для Windows метод для "catch ctrl + c". Я представляю, что он там называет.