【发布时间】: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 我认为从概念上讲这是有道理的,但挑战还在于父进程可能仍在运行。我只想从 _ 父级优雅地终止进程。