【问题标题】:Sending an arbitrary Signal in Windows?在 Windows 中发送任意信号?
【发布时间】:2010-09-13 11:56:14
【问题描述】:

Linux 支持使用 kill-Command 向进程发送任意 Posix 信号,例如 SIGINTSIGTERM。虽然SIGINTSIGTERM 只是以友好或不那么友好的方式结束进程的无聊旧方法,但SIGQUIT 旨在触发核心转储。这可用于触发正在运行的 Java VM 打印出线程转储,包括所有正在运行的线程的堆栈跟踪——太棒了!打印调试信息后,Java VM 将继续执行之前的操作;事实上,线程转储只是发生在另一个具有最高优先级的衍生线程中。 (您可以使用kill -3 <VM-PID> 自己尝试一下。)

请注意,您还可以使用 sun.misc-package 中的(不支持!)SignalSignalHandler 类注册自己的信号处理程序,这样您就可以享受各种乐趣。

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

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

【问题讨论】:

  • Sun 警告不要在 com.sun 层次结构中使用类,因为它们可以(并且确实)在版本之间,有时甚至在平台之间任意更改。
  • 我知道,这就是我写 unsupported(感叹号)的原因。这只是一个旁白,并不是问题的核心。
  • 我正在寻找自己生成堆栈转储...太糟糕了 Sun 没有从 Java 托盘图标中添加这种可能性。

标签: java windows utilities


【解决方案1】:

如果您想要显式/以编程方式杀死任何类型的另一个程序/进程,在 SysInternals 的 pstools 中有一个名为“pskill”的小工具,其行为就像 Unixen“kill”一样。

如果您想要其他内容,请继续阅读(尽管我可能对以下某些细节有误 - 自从我上次仅使用 WinAPI 和 Charles Petzold 的优秀书籍“Windows 编程”用 C 语言开发 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 向该窗口发送消息。

【讨论】:

  • 我认为 Windows 也不会发送 WM_QUIT,至少在关闭窗口时不会发送。
  • 啊,你让我研究这个......这总是一件好事,因为自从我直接使用 Win API 开发以来,它已经存在了好久。现在我更清楚了。
  • 这只是 UI 应用程序的行为 - 如果您的应用程序没有 UI(例如控制台应用程序),则此答案不正确,没有 UI 的本机关闭或关闭挂钩的一种可能性是 @ 987654322@
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    在 Windows 中,一切都围绕着 Win32 消息。我不相信有一个命令行工具可以做到这一点,但在 C++ 中,您可以使用 FindWindow 向另一个 Windows 程序发送任意消息。例如:

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

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

    【讨论】:

      【解决方案4】:

      SIGINT等信号可以使用windows-kill发送给程序,语法为windows-kill -SIGINT PID,其中PID可以通过微软的pslist获取。

      关于捕获 SIGINT,如果您的程序是 Python 中的,那么您可以像 this solution 那样实现 SIGINT 处理/捕获。

      【讨论】:

        【解决方案5】:

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

        它没有回答您最初的问题,但希望可以让您获得相同的结果。

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

        【讨论】:

          【解决方案6】:

          我只是想知道来自微软现在拥有的PsToolsSysInternals 是否会对您有所帮助。

          【讨论】:

          • 对我不起作用(pskill 不起作用 表现为 Ctrl+C 或 Ctrl+Break...)
          【解决方案7】:

          Ruby 能够(至少模拟)Windows 上的 SIGINT SIGKILL 等,并捕获这些消息。可能想检查一下。

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

          还有一个“捕获 ctrl+c”的 windows 等效方法,我想这就是它在那里调用的方法。

          【讨论】:

          • 一个例子?
          • OK 添加更多,或者您想要一个 ruby​​ 示例? :)
          猜你喜欢
          • 2016-09-29
          • 1970-01-01
          • 2011-07-14
          • 2014-12-07
          • 2021-12-01
          • 2018-11-25
          • 2021-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多