优雅的 Win32 无窗口进程终止
Posted
技术标签:
【中文标题】优雅的 Win32 无窗口进程终止【英文标题】:Graceful Win32 windowless process termination 【发布时间】:2021-09-15 22:09:44 【问题描述】:我正在开发一个用 C# 编写的控制台应用程序,我在其中触发 Application.Run()
来管理系统托盘。应用程序本身是无窗口的。
这是我遇到的挑战 - 当用户关闭应用程序时,我需要进行清理,并确保从系统托盘中删除应用程序图标。当我附加并分配了一个控制台窗口时,这很容易做到,因为我可以使用SetConsoleCtrlHandler
。
但是,当我没有分配和附加控制台窗口时,问题就开始了(因为应用程序大部分时间都是这样运行的)。我想优雅地从另一个进程中终止该进程,以便我可以在我的应用程序中调用 SetConsoleCtrlHandler
并进行清理。但是,我在 Windows 上找到的所有指导都是通过发送 WM_CLOSE
消息,这不适用,因为我没有任何可用于该应用程序的窗口。
所以,考虑到有问题的应用程序是使用CreateProcess
启动的,我有进程 ID、句柄和主线程 ID。
问题:我有没有办法优雅地告诉另一个应用程序终止而不调用TerminateProcess
(这不会给任何清理余地)?
我想我可能需要实现一个命名管道,以便在这种情况下我可以在客户端应用程序和“服务器”之间进行通信,但是感觉有点过分了.
【问题讨论】:
我们过去的做法是让 process1 在启动时将其句柄传递给 process2。然后 process2 可以使用GetExitCodeProcess 来确定父级是否已退出。如果这更适合您的应用,您也可以等待父进程而不是轮询。 我认为如果你不设置它就不可能进行清理。您需要使用消息(喜欢但不是必需的WM_CLOSE
)或实现自己的通信。
为什么不直接运行一个隐藏窗口来接收消息。我认为您需要在通知区域(又名系统托盘)中运行一个窗口。你的图标如何在没有窗口的情况下获取消息
如果你成功地将一个图标放入了 shell 通知区域,那么显然你必须为NOTIFYICONDATAW 提供了一个有效的HWND
。是什么让您无法使用该窗口进行交流?
@RetiredNinja 我认为从概念上讲这是有道理的,但挑战还在于父进程可能仍在运行。我只想从 _ 父级优雅地终止进程。
【参考方案1】:
我认为,你应该实现自己的沟通方式。恕我直言,最简单的方法是使用命名事件。控制台应用程序创建命名事件并有时检查它。外部应用程序设置事件以防退出第一个应用程序。 此方法仅适用于 Windows。
【讨论】:
一个名为EventWaitHandle
的也可以用于Windows以外的操作系统。
将此标记为答案,因为这是我实现的唯一可靠的方法。以上是关于优雅的 Win32 无窗口进程终止的主要内容,如果未能解决你的问题,请参考以下文章
cef3嵌入win32无标题栏窗口,怎么来移动这个cef窗口
Win32 使用 SetCurrentProcessExplicitAppUserModelID 关联多个进程 在任务栏合并 WPF 多进程窗口