【问题标题】:Gracefully shutting down system tray application优雅地关闭系统托盘应用程序
【发布时间】:2013-04-16 16:54:43
【问题描述】:

我有一个在系统托盘(通知区域)中运行的非常基本的应用程序。 Main 方法如下所示:

using (NotifyIcon notifyIcon = new NotifyIcon())
{
    notifyIcon.ContextMenuStrip = new ContextMenuStrip();
    notifyIcon.ContextMenuStrip.Items.Add(new ToolStripMenuItem(
        "Exit", 
        null, 
        delegate { App.Exit(); }
        )
    );

    notifyIcon.Icon = Properties.Resources.MyIcon;
    notifyIcon.Visible = true;

    Application.Run();
}

到目前为止,这工作正常(我可以使用上下文菜单中的退出选项并且应用程序正确退出。但是,当软件卸载时我需要退出应用程序。现在我正在使用我的 taskkill WiX安装程序来做到这一点(也许有更好的方法?)。问题是如果我这样做taskkill /im myapp.exe,通知区域中的图标会消失但进程仍在运行。如果我用taskkill /f /im myapp.exe强制关闭它,那么进程结束,但图标仍然存在(直到我将鼠标悬停在它上面)。有没有办法删除图标并从单独的进程中结束进程?

【问题讨论】:

  • 您需要告诉您的应用程序退出,以便它可以从系统托盘中取消注册。 taskkill 只是从内存中卸载进程,进程没有机会做任何响应。

标签: c# .net winforms


【解决方案1】:

向您的应用程序添加隐藏表单。这将是 Application.Run() 的一个参数。当表单关闭时,您的应用程序将退出。

要在 WiX 中关闭表单,请使用 util:CloseApplication1 并将 CloseMessage 属性设置为 true。

【讨论】:

  • 成功了,非常感谢。仅供参考,对于其他任何人:在调用 Application.Run(myForm) 之前,我通过在新建表单上将 ShowInTaskbar 属性设置为 false 并将 WindowState 设置为 FormWindowState.Minimized 创建了一个不可见的表单。
  • 好的,经过进一步测试,这并不总是有效。如果我在尝试关闭应用程序之前打开上下文菜单,图标会消失,但进程会继续运行。如果我不右键单击并调出上下文菜单,一切都会很好。知道发生了什么吗?上下文菜单本身似乎很无害...
  • 可能是图标和菜单控件需要一个在消息循环中运行的容器,以便在消息循环终止之前将它们卸载。尝试使用 WinForm 设计器将图标和菜单放置在表单上。即使它们的包含表单被隐藏,它们仍然会显示。
  • 好的,好主意,但这仍然行不通。我试图用调试器仔细检查一下,看起来Application.Run 仍在运行(即使通知图标消失了)。就好像上下文菜单接管了应用程序的主要形式一样?但这并不能解释通知图标是如何被删除的……这真的很奇怪。
  • 只是为了在我之前的评论中添加更多信息,我覆盖了表单上的 WndProc 方法并在其中设置了一个断点以查看会发生什么。当我使用 taskkill 时,如果不打开上下文菜单,我会收到一堆消息。但是,如果我打开上下文菜单然后调用 taskkill 我什么也得不到。我怀疑上下文菜单以某种方式接管了该过程的主要形式?
【解决方案2】:

我决定采取不同的方法。我添加了一个命令行参数来指示我要关闭。然后,此开关将使用RegisterWindowMessage 定义的自定义消息调用 Win32 API SendMessage(奇怪的是 PostMessage 不起作用)。然后,WiX 安装程序将使用此命令行参数执行进程,并且现在可以正常关闭。好痛啊……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多