如何检测 Windows 关闭或注销

Posted

技术标签:

【中文标题】如何检测 Windows 关闭或注销【英文标题】:How to detect Windows shutdown or logoff 【发布时间】:2011-10-11 14:42:58 【问题描述】:

我需要检测 Windows 何时关闭(或重新启动)或用户何时注销。我需要在关闭应用程序之前正确关闭应用程序。 我注意到在 Windows 关闭日时不会引发退出应用程序事件。

我看了帖子Is there a way in c# to detect a Windows shutdown/logoff and cancel that action (after asking the user)

但我不确定在关闭之前我应该​​在哪里执行操作。 谢谢。

【问题讨论】:

半相关,Force application close on system shutdown 【参考方案1】:

Attach an event handler method 到SystemEvents.SessionEnding event,并且每次引发事件时都会调用您的处理程序方法。如果您愿意,处理此事件将允许您取消挂起的注销或关闭。 (尽管这实际上不像在当前操作系统中听起来那样有效;有关更多信息,请参阅MSDN documentation here。)

如果您不想取消该事件,而只是对其做出适当的反应,则应改为处理 SystemEvents.SessionEnded event。

但是,您必须确保在应用程序关闭时分离您的事件处理程序,因为这两个都是静态事件。

【讨论】:

这个线程现在可能已经死了,但是如果你的应用程序在关闭之后启动会发生什么。这两个事件是否仍然有效,因为从技术上讲你已经错过了它。这就是我现在遇到的问题。我的应用程序旨在保持运行,并且在关闭时它会在被 Windows 杀死以准备关闭后尝试重新启动。 @Ultratrunks 你正在打一场失败的战斗。应用程序无法可靠地防止系统关闭,它所能做的就是对其做出反应。 @CodyGray 根据我的评论,我不是在寻找任何阻止关闭的东西。我只是想知道它。实际上,我现在无意中阻止了关机,因为我的应用程序在关机过程开始后尝试启动,它立即崩溃并在屏幕上留下一个窗口,防止发生关机。这很麻烦,所以我希望能够查询系统并询问“您正在关闭吗?”所以我可以采取相应的行动。 您能否详细说明为什么需要取消附加事件?您的应用程序正在关闭。任何管理都不会泄漏。非托管内存会保持打开状态吗? 有没有办法在不关闭或注销的情况下测试这些事件?【参考方案2】:

如果您的代码未在非交互式会话(例如系统服务)中运行,您可以通过pinvoke 使用本机解决方案:

//SM_SHUTTINGDOWN = 0x2000
bool bShutDownPending = GetSystemMetrics(SM_SHUTTINGDOWN) != 0;

【讨论】:

当然,请记住,这是一个 轮询 解决方案 - 没有回调,没有事件处理 - 您必须检查直到满足此条件。 如何在C#中使用它?我只在 C++ 中找到 @MahmoudAl-Qudsi:当然。它只是增加了一点工作。只需创建一个工作线程,在循环中轮询该值并使用结果设置一个locked 全局布尔变量,或者调用您的自定义事件处理程序。重要的部分是确保它不会“吃掉”太多的 CPU 周期。为此,只需输入Sleep(10);在每个循环中调用。此外,您可以实现一个停止事件以退出该线程。 既然有异步事件驱动的解决方案,你应该不需要用单独的线程和 CPU 循环来浪费系统资源。 @MahmoudAl-Qudsi:你看到我的解释了吗?如果按照我的建议实施,则不会有“浪费系统资源”对任何措施都很重要,尤其是。对于 .NET 应用程序。已经有一段时间了,我找不到我的确切应用程序,但我提供上述解决方法的原因是针对 .NET 的 SystemEvents.SessionEnded 不可用的情况。否则显然使用它。此外,您可能想知道用户是否正在注销,例如,在实施另一个事件时。在这种情况下,这个解决方案更加健壮,根本不需要轮询。【参考方案3】:

现在你应该使用这样的东西:

private static int WM_QUERYENDSESSION = 0x11;
protected override void WndProc(ref System.Windows.Forms.Message m)

    if (m.Msg==WM_QUERYENDSESSION)
    
        MessageBox.Show("queryendsession: this is a logoff, shutdown, or reboot");
    
    
    base.WndProc(ref m);

【讨论】:

以上是关于如何检测 Windows 关闭或注销的主要内容,如果未能解决你的问题,请参考以下文章

如何让Win10在重启关机或注销时自动关闭应用程序

如何让 .NET Windows 服务检测登录、注销和切换用户事件?

windows的切换用户、注销和重新启动有啥区别?

如何从 closeEvent 处理使用 PyQt4 检测注销/关闭?

在 Windows Phone 8.1 XAML 中检测停用和应用关闭

c# 如何截获windows关机或注销消息