【问题标题】:Tray icon does not disappear on killing process托盘图标在杀死过程中不会消失
【发布时间】:2011-01-19 16:36:21
【问题描述】:

我的应用程序有一个窗口服务。当我通过使用任务管理器终止进程来停止它时,托盘图标不会消失。它是窗口错误还是其他什么?我们有解决这个问题的办法吗?在此先感谢:)。

【问题讨论】:

标签: windows-services windows-xp c#-2.0


【解决方案1】:

您可以通过调用指定的 NotifyIcon 对象的 Dispose() 方法让图标消失。在大多数情况下,这些容器对象不是应用程序中组件树的一部分,因此它不会因终止进程而消失。当用户在图标上移动时,图标找不到它的父级,因此它消失了。但是通过调用 Dispose 方法,它至少在我的应用程序中消失了。所以:

//creating a NotifyIcon
NotifyIcon notifyicon = new NotifyIcon();
notifyicon.Text = "Text"; 
notifyicon.Visible = true; 
notifyicon.Icon = new Icon(GetType(),"Icon.ico");
//let it disappear
notifyicon.Dispose();

【讨论】:

  • 谢谢,听起来不错,但我不知道该把代码放在哪里。如果你能帮助我,那就太好了。
  • 我认为您应该定义一个方法,以便当您的应用程序退出时它会调用该方法。因此,如果它是一个窗口应用程序(带有表单)。我认为你会适当地使用方法 Application.Run(yourForm);表单关闭后,方法完成,所以main方法继续。如果你在你的主类中定义了 notifyIcon,你可以让它在 Run 方法之后消失。但是,我当然不能笼统地回答这个问题。结束应用程序时,您需要找到一个有效的线程。
  • 编辑(我重读了您的问题):如果您向 Process.Exited 事件添加一个方法并且该方法完成了工作,我认为它应该可以工作,但我还没有测试它。祝你好运
  • 嗨,我想它应该对我有用。谢谢你让我成为一个快乐的人:)。
  • @Lalit,你可以做的另一件事(但这当然不是一个优雅的解决方案,当程序加载时,启动另一个程序来监视你的第一个程序,当第一个程序关闭时,另一个会使图标消失。如果第二个被杀死,第一个只是创建一个新程序。但是,这种工作方式当然看起来很像病毒的行为。
【解决方案2】:

这个问题没有解决办法。如果您使用任务管理器终止进程,它不会收到终止通知,因此无法从托盘中删除其图标。尝试以这种方式避免杀死进程。您可以使用net start/stop 杀死服务或使用services.msc GUI。

【讨论】:

    【解决方案3】:

    使用这个工具http://www.codeproject.com/Articles/19620/LP-TrayIconBuster

    它遍历 TrayNotifyWnd 和 NotifyIconOverflowWindow 中的 ToolBarButtons 并删除那些具有空文件名的按钮。

    【讨论】:

    • 完美,我一直在寻找一种自动化的方式来处理这个问题。此应用程序不能“按需”运行(它希望保留为持久托盘应用程序)。它还删除了我设置中的几个有效图标。但是,提供了源代码,所以我应该能够适应我的需要。
    【解决方案4】:

    将鼠标移到图标上,它就会消失。我在所有版本的 Windows 中都注意到了这种行为,包括 Win 7。

    【讨论】:

    • 是的,它可以工作,但我必须通过代码让它消失。我的意思是我的测试团队正在运行一些脚本来停止该服务,我觉得他们实际上是在杀死进程而不是优雅地退出服务。我必须为他们找到解决方案(你知道测试人员:D)。
    • 这并不完全是一个修复。更像是一个肮脏肮脏的黑客。
    • 这是一个 windows 的东西,我能想到的唯一建议是创建一个帮助应用程序(隐藏),它有一个简单的目的来监视主应用程序何时意外中止(在计时器上),如果第一个应用程序出现故障 - 然后采取行动,该行动究竟是什么 - 我真的不知道。
    • 投反对票,因为没有答案,也没有提示为什么没有答案......为什么它经常被投赞成票?
    【解决方案5】:

    在各种应用程序中,我也经常注意到这一点。只有当您将鼠标移到图标上时,才会注意到应用程序的死亡。

    我认为“错误”在于 Windows,而不是您的应用程序。 (我不愿将其称为“错误”,因为这可能是一个有意识的决定,将其留在其中。资源管理器可以检查注册图标的应用程序是否仍在运行,但这可能太贵了。)

    【讨论】:

      【解决方案6】:

      如果应用程序被强制终止(例如通过任务管理器),则 Windows 不会删除通知图标。 Windows 资源管理器甚至不会注意到应用程序已经消失,直到它尝试向拥有通知图标的窗口发送消息(通常是鼠标移动消息)。届时,Windows 将从通知区域中删除现已失效的图标。

      鉴于您是 can't intercept TerminateProcess,您的程序无法自行解决此问题。

      我猜想 Windows 资源管理器可以监视所有者窗口被破坏(当应用程序意外退出时),但它没有。

      即使应用程序正常关闭,它仍必须记住删除其任何通知图标。也就是说:如果您在应用程序关闭时(甚至是正常关闭)不调用Shell_NotifyIcon(NIM_DELETE)(相当于NotifyIcon.Dispose),则图标将一直保留在那里,直到鼠标移到它上面。

      哦,如果这是显示通知图标的服务进程,请注意 Windows Vista 和 Windows 7 中的会话 0 隔离会破坏它。

      【讨论】:

        【解决方案7】:

        我通过处理ThreadException 事件并在该事件处理程序中处理托盘图标来完成它。

        【讨论】:

        • 嘿,控制不会在杀死进程时发生 ThreadException,所以它不会工作:(.
        • @lalit 好吧,如果您实际上正在使用服务(即扩展 ServiceBase),则可以覆盖 Dispose 方法。这完全取决于您拥有什么样的应用程序以及创建托盘图标的位置。
        • @lalit 嗯....您使用的是真正的服务吗? (如,扩展ServiceBase)?很难告诉您要做什么以及在哪里做,因为我们不知道确切您正在开发什么样的应用程序以及您如何构建 TrayIcon 以及您将它存储在哪里。代码肯定会有所帮助。如果您实际上正在使用服务并且您在服务类中创建了 TrayIcon(我不确定这是否可能),您可以将 TrayIcon 放在 this.components 集合中,它会在服务被释放时被释放。但我不确定你是不是这样做的,所以给我代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-16
        • 1970-01-01
        • 1970-01-01
        • 2016-01-24
        • 2015-02-18
        • 2021-12-02
        • 1970-01-01
        相关资源
        最近更新 更多