在Windows中发送任意信号?

时间:2008-09-26 15:09:24

标签: java windows utilities

Linux支持使用SIGINT - 命令向进程发送SIGTERMkill等任意Posix信号。虽然SIGINTSIGTERM只是无聊的方式以友好或不友好​​的方式结束流程,但SIGQUIT意味着触发核心转储。这可以用来触发正在运行的Java VM打印出一个线程转储,包括所有正在运行的线程的堆栈跟踪 - 整洁!打印完调试信息后,Java VM将继续执行以前的操作;事实上,线程转储只发生在另一个具有最高优先级的衍生线程中。 (您可以使用kill -3 <VM-PID>自行尝试。)

请注意,您还可以使用Signal - 包中的(不支持!)SignalHandlersun.misc类注册自己的信号处理程序,这样您就可以获得各种乐趣它

但是,我还没有找到一种向Windows进程发送信号的方法。信号由某些用户输入创建:Ctrl-C在两者上触发SIGINT例如,平台。但是,在Windows上手动将信号发送到正在运行但非交互式的进程似乎没有任何实用性。显而易见的解决方案是使用Cygwin kill可执行文件,但是虽然它可以使用适当的Windows API结束Windows进程,但我无法发送SIGBREAK(Windows等效于SIGQUIT)它;事实上,我认为它能够发送到Windows进程的唯一信号是SIGTERM

因此,长话短说并重复标题:如何向Windows中的进程发送任意信号?

7 个答案:

答案 0 :(得分:13)

如果你想要的是明确地/程序化地杀死任何类型的另一个程序/进程,在SysInternals的pstools中有一个名为“pskill”的小工具,其行为就像Unixen“kill”那样。

如果你想要别的东西,继续阅读(虽然我可能在下面的一些细节上错了 - 自从我上次使用WinAPI和Charles Petzold的优秀书籍“用于Windows编程”开发了一个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向该窗口发送消息。

答案 1 :(得分:8)

Windows不是POSIX。它没有信号。控制台程序获得的唯一“信号”是他们调用SetConsoleCtrlHandler,在这种情况下,可以通知用户按下Ctrl + C,Ctrl + Break,关闭控制台窗口,注销或关闭系统故障。

其他一切都是通过IPC完成的,通常使用窗口消息或RPC。查看Sun的文档,看看是否有办法在Windows JRE上执行您所要求的操作。

答案 2 :(得分:3)

在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);
}

这也可以使用com interop在C#中完成。

答案 3 :(得分:1)

您还可以使用jconsole查看所有正在运行的线程的堆栈跟踪。这适用于Windows以及支持Java的任何其他操作系统。 jconsole还有许多其他不错的功能,内存图,cpu图等。

它没有回答你原来的问题,但希望你能得到相同的结果。

如果您不熟悉jconsole,请查看Using JConsole文档。

答案 4 :(得分:0)

我只是想知道现在微软拥有的PsTools SysInternals是否能帮到你。

答案 5 :(得分:0)

Ruby在某种程度上能够(至少模仿)Windows上的SIGINT SIGKILL等,并捕获这些消息。可能想看看它。

在windows下,ruby如何“向该进程发送信号SIGINT”实际上是在该PID上调用TerminateProcess或等效的。

还有一个用于“捕捉ctrl + c”的窗口等效方法我想象它就是它所谓的。

答案 6 :(得分:0)

SIGINT和其他信号可以使用windows-kill通过语法windows-kill -SIGINT PID发送到程序,其中PID可以通过Microsoft的pslist获得。

关于捕获SIGINT,如果您的程序使用Python,则可以像在this solution中一样实现SIGINT处理/捕获。