【问题标题】:Catch Windows terminal closing on running process在正在运行的进程中捕获 Windows 终端关闭
【发布时间】:2024-01-05 21:57:01
【问题描述】:

在命令提示符窗口中,我有一个正在运行的进程。在进程仍在执行时,我单击命令提示符窗口一角的(红色)“X”。命令提示符窗口关闭,正在运行的进程终止。

在 Linux 上,关闭正在运行的进程的父终端将发送该进程SIGHUP。如何在 Windows 上捕获此事件?

【问题讨论】:

    标签: windows process terminal signals command-prompt


    【解决方案1】:

    SIGHUP 的等价物是通过您向SetConsoleCtrlHandler 注册的回调提供的。您的回调函数将在 dwCtrlType = CTRL_CLOSE_EVENT 的任意线程池线程上调用。您有 5 秒的时间进行清理,您无法取消关闭。

    示例代码在this MSDN article中提供

    【讨论】:

      【解决方案2】:

      这不能直接从命令提示符处完成。您需要一个辅助的任何东西(vbs、powershell 或自定义 MyApp.exe)来在 cmd.exe 关闭时捕获它并做出相应的反应。

      例如,VBS WMI 监视器。

      strComputer = "."
      Set objSWbemServices = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!" & "\\" & strComputer & "\root\cimv2")
      Set objEventSource = objSWbemServices.ExecNotificationQuery( "SELECT * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name = 'cmd.exe'")
      Set objEventObject = objEventSource.NextEvent()
      Wscript.Echo "CMD.exe closed"
      

      【讨论】:

      • 虽然我更喜欢激光聚焦监视器来跟踪 cmd.exe 的确切 PID,这样我们就不会意外触发不同的 cmd.exe 实例。你还是明白了。
      • 此外,这不会确定 Red X 或批处理是否简单完成,需要在批处理脚本的末尾添加额外的逻辑以在批处理结束之前取消 WMI 监视器,以便它不会'在正常完成时不触发。
      • 从实际的编程语言中,您可以使用控制台控制处理程序并捕获控制台关闭事件。
      • 有关 ConsoleCtrlHandler 的更多详细信息,请参见 Hans 的帖子。
      【解决方案3】:

      “SIGHUP”...在 Windows 8.1 pro + Node.js 0.10.24 上测试工作正常..

      process.on('SIGHUP', function(){
          //Your code goes here.
      });
      

      【讨论】: