Отправлять произвольный сигнал в Windows? - PullRequest
26 голосов
/ 26 сентября 2008

Linux поддерживает отправку произвольного Posix-сигнала, такого как SIGINT или SIGTERM, процессу, использующему kill -команду. В то время как SIGINT и SIGTERM являются просто скучными старыми способами завершать процесс дружественным или не очень дружественным способом, SIGQUIT предназначен для запуска дампа ядра. Это может использоваться для запуска работающей Java VM для распечатки дампа потока, включая трассировки стека всех запущенных потоков - аккуратно! После печати отладочной информации Java VM продолжит делать то, что делал раньше; фактически дамп потока просто происходит в другом порожденном потоке с максимальным приоритетом. (Вы можете попробовать это самостоятельно, используя kill -3 <VM-PID>.)

Обратите внимание, что вы также можете зарегистрировать свои собственные обработчики сигналов, используя (неподдерживаемые!) Классы Signal и SignalHandler в пакете sun.misc, так что вы можете развлекаться с ним.

Однако мне еще предстоит найти способ отправки сигнала процессу Windows. Сигналы создаются определенными пользовательскими входами: Ctrl-C запускает SIGINT, например, на обеих платформах. Но, похоже, нет какой-либо утилиты для ручной отправки сигнала запущенному, но неинтерактивному процессу в Windows. Очевидное решение состоит в том, чтобы использовать исполняемый файл Cygwin kill, но, хотя он может завершать процессы Windows, используя соответствующий API Windows, я не смог отправить SIGBREAK (Windows эквивалент SIGQUIT) с ним; на самом деле я думаю, что единственный сигнал, который он может послать процессам Windows, это SIGTERM.

Итак, для краткости и повторения заголовка: Как отправить произвольный сигнал процессу в Windows?

Ответы [ 6 ]

13 голосов
/ 26 сентября 2008

Если вы хотите явно / программно уничтожить другую программу / процесс любого рода, в pstools SysInternals есть небольшой инструмент с именем "pskill", который ведет себя так же, как и Unixen "kill".

Если вы хотите что-то еще, продолжайте читать (хотя я могу ошибаться в некоторых особенностях ниже - это было давно, с тех пор как я в последний раз разрабатывал программу для Windows на C, используя только WinAPI и превосходные книги Чарльза Петцольда «Программирование для Windows» в качестве руководства).

В Windows у вас нет правильных «сигналов», какие функции WinMain и WinProc получают из операционной системы - это простые сообщения . Например, когда вы нажимаете на кнопку «X» окна, Windows отправляет обработчику этого окна сообщение WM_CLOSE. Когда окно удалено, но программа все еще работает, оно отправляет WM_DESTROY. Когда он собирается выйти из основного цикла обработки сообщений, WinMain (не WinProc) получает WM_QUIT. Ваша программа должна реагировать на все это, как и ожидалось - на самом деле вы можете разработать «не подлежащее закрытию» приложение, не делая то, что должно, после получения WM_CLOSE.

Когда пользователь выбирает задачу в диспетчере задач Windows и нажимает «Завершить задачу», ОС отправит WM_CLOSE (и еще одну, которую я не помню). Однако, если вы используете «Завершить процесс», процесс прекращается напрямую, сообщения никогда не отправляются (источник: The Old New Thing

Я помню, что был способ получить HWND окна другого процесса, как только вы узнали, что другой процесс может отправить этому окну сообщение через функции PostMessage и DispatchMessage.

8 голосов
/ 26 сентября 2008

Windows не POSIX. У него нет сигналов. Единственные «сигналы», которые получают консольные программы, это если они вызывают SetConsoleCtrlHandler, и в этом случае он может быть уведомлен о том, что пользователь нажал Ctrl + C, Ctrl + Break, закрыл окно консоли, вышел из системы или выключил систему. .

Все остальное делается с помощью IPC, как правило, с помощью оконных сообщений или RPC. Посмотрите документацию Sun, чтобы узнать, есть ли способ выполнить то, что вы просите в Windows JRE.

3 голосов
/ 26 сентября 2008

В Windows все вращается вокруг сообщений Win32. Я не верю, что для этого есть инструмент командной строки, но в C ++ вы можете использовать FindWindow для отправки произвольного сообщения другой программе Windows. e.g.:

#define WM_MYMSG  ( WM_USER+0x100 )
HWND h = ::FindWindow(NULL,_T("Win32App"));
if (h) {
    ::PostMessage(h, WM_MYMSG, 0, 0);
}

Это также можно сделать в C # с помощью com-взаимодействия.

1 голос
/ 26 сентября 2008

Вы также можете использовать jconsole для просмотра трассировки стека всех запущенных потоков. Это будет работать в Windows и любой другой ОС, поддерживающей Java. jconsole также имеет много других полезных функций, графики памяти, графики процессора и т. д.

Он не отвечает на ваш первоначальный вопрос, но, надеюсь, позволит вам получить те же результаты.

Если вы не знакомы с jconsole, ознакомьтесь с документацией Using JConsole .

0 голосов
/ 15 марта 2012

Ruby каким-то образом способен (по крайней мере эмулировать) SIGINT SIGKILL и т. Д. На окнах и перехватывать эти сообщения. Возможно, стоит проверить это.

То, как ruby ​​«отправляет сигнал SIGINT этому процессу» под Windows, фактически вызывает TerminateProcess или эквивалент для этого PID.

Есть также эквивалентный для Windows метод для "перехвата Ctrl + C". Я думаю, это то, что он там вызывает.

0 голосов
/ 26 сентября 2008

Мне просто интересно, поможет ли вам PsTools из, теперь принадлежащего Microsoft, SysInternals .

...