25

是否可以订阅在 Windows 进入或退出睡眠或休眠状态时触发的 Windows 事件?

我需要让我的应用程序知道计算机何时进入睡眠状态以进行一些清理,并避免在它退出睡眠时出现计时问题。

4

6 回答 6

21

Microsoft.Win32.SystemEvents.PowerModeChanged活动将为您提供此信息。此事件在 Microsoft 迄今为止发布的所有 .NET 框架变体中都可用。

于 2008-10-23T03:06:22.517 回答
6

在 .NET 中,使用PowerModeChanged事件。在 Win32 中,使用WM_POWERBROADCAST消息。

于 2008-10-23T03:05:15.763 回答
4

在 Visual Studio 2005 C++ MFC 应用程序中,您需要向ON_MESSAGE()消息映射中添加一个以查找WM_POWERBROADCAST消息,如下例所示:

BEGIN_MESSAGE_MAP(CFrameworkWndDoc, CWindowDocument)
    //{{AFX_MSG_MAP(CFrameworkWndDoc)
    ON_WM_CHAR()
    ON_WM_TIMER()
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_POWERBROADCAST, OnPowerMsgRcvd)
END_MESSAGE_MAP()

然后,您需要添加消息处理函数以及类定义更改以声明消息处理程序的成员函数,以便您可以检查wParam消息类型的变量,如下面的框架:

// Handle the WM_POWERBROADCAST message to process a message concerning power management
// such as going to Sleep or Waking Up.
LRESULT CFrameworkWndDoc::OnPowerMsgRcvd(WPARAM wParam, LPARAM lParam)
{
    switch (wParam) {
        case PBT_APMPOWERSTATUSCHANGE:
            TRACE0("PBT_APMPOWERSTATUSCHANGE  received\n");
            break;
        case PBT_APMRESUMEAUTOMATIC:
            TRACE0("PBT_APMRESUMEAUTOMATIC  received\n");
            break;
        case PBT_APMRESUMESUSPEND:
            TRACE0("PBT_APMRESUMESUSPEND  received\n");
            break;
        case PBT_APMSUSPEND:
            TRACE0("PBT_APMSUSPEND  received\n");
            break;
    }

    return 0;
}

我所看到的是,在调试器中启动的 Windows 7 上运行的应用程序中使用上述测试,然后我手动使运行应用程序的 PC 进入睡眠状态,我将看到以下消息:

PBT_APMSUSPEND  received

然后,当 PC 重新启动并登录时,我将在调试器输出窗口中看到一条接一条的两条消息:

PBT_APMRESUMESUSPEND  received
PBT_APMRESUMEAUTOMATIC  received

到目前为止,我发现的所有内容都表明您不知道您是退出睡眠状态还是休眠状态。我仍在进一步研究暂停或恢复文件和设备处理时需要做什么。我已经看到恢复后 COM 端口的文件句柄不再有效的迹象。我也不确定实例数据库连接的其他进程的接口。

除了标准的睡眠和休眠电源管理状态外,Microsoft 还引入了Windows 8 和 8.1 的连接待机电源状态,根据应用程序的类型,它具有一些应用程序设计分支。

桌面应用程序通常不需要额外的工作来与连接待机集成。

Desktop Activity Moderator (DAM) 是 Windows 组件,可在连接待机期间暂停所有桌面应用程序并限制第三方系统服务的运行时间。DAM 的目的是保持与现有应用程序和服务的基本软件兼容性,但减轻它们在睡眠期间对电池寿命的影响。

在 DAM 阶段完成后,Windows 会阻止桌面应用程序在连接待机的任何部分运行。Windows 允许第三方系统服务在完成 DAM 阶段后以节流模式执行。在这种模式下,第三方服务每 30 秒可以运行不超过一秒的挂钟时间。

来自 Intel的 Lynn Merrill 的优雅应用程序暂停艺术有一些关于在 Windows 下处理与电源管理相关的各种 Windows 消息类型的信息,但是它是 2005 年的,因此并非所有材料都可能与 Windows XP 之后的 Windows 有关。在本文档中描述的消息序列中至少有一条不再使用的消息,从 Windows Vista 开始,PBT_APMQUERYSUSPEND用于请求应用程序是否能够挂起的消息不再被 Windows 使用。该SetThreadExecutionState()函数现在用于指示线程不能因更改为睡眠或休眠状态而中断。有关电源管理状态消息更改的详细信息,请参阅 stackoverflow Can't catch sleep suspend messages (winxp)中的答案。

自 Windows XP 以来的系统电源状态事件

自 Windows XP 以来,Microsoft 改进了电源管理,因为各种版本的 Windows 操作系统共享更多组件,并且 Windows 版本现在部署在需要更仔细电源管理的电池的小型设备上。请参阅注册电源事件。既有RegisterPowerSettingNotification()功能又有UnregisterPowerSettingNotification()功能。

应用程序或服务使用该RegisterPowerSettingNotification 功能注册通知。当相应的电源设置发生变化时,系统会发送如下通知:

  • 应用程序接收到WM_POWERBROADCAST带有 a wParamofPBT_POWERSETTINGCHANGE和 an的消息,该消息lParam指向一个 POWERBROADCAST_SETTING结构。
  • 服务HandlerEx通过调用该函数接收对其注册的回调函数的调用RegisterServiceCtrlHandlerExlpEventData发送给回调函数的 参数HandlerEx指向一个POWERBROADCAST_SETTING结构。

POWERBROADCAST_SETTING结构中,PowerSetting成员包含标识通知的 GUID,数据成员包含电源设置的新值。

另请参阅电源管理函数以获取自 Windows Vista 以来 Windows API 中的电源管理函数列表。

系统电源状态和电池状况

您可以使用 Windows 系统服务 API 函数GetSystemPowerStatus()来检索当前的电源状态。

检索系统的电源状态。该状态指示系统是使用交流电源还是直流电源运行、电池当前是否正在充电、电池寿命剩余多少以及电池保护程序是打开还是关闭。

但是请注意,SYSTEM_POWER_STATUS结构中返回的信息是关于电池状态和 AC/DC 电源的,而不是实际的设备电源状态,例如 Sleep 或 Hibernate

如果 Windows 设备处于睡眠或休眠状态,您的应用程序将不会运行,因此该函数不能用于确定当前的 Windows 电源状态。我包含此注释,因为它可能对在研究此主题时到达此帖子的人有用。

于 2015-06-24T17:30:27.960 回答
3

可以监控Win32_PowerManagementEvent WMI 事件

于 2008-10-23T02:11:32.703 回答
3

不确定您希望多久监控一次,但如果您在 .NET 中编写服务,您可以覆盖 ServiceBase,将 CanHandlePowerEvent 设置为 true,然后您将通过 PowerBroadcastStatus 枚举收到电源更改通知。

于 2008-10-23T03:58:32.037 回答
0

您可以订阅 NetworkChange.NetworkAvailabilityChanged 和 NetworkChange.NetworkAddressChanged。

我通常会启动一个两秒钟的计时器,以便在超时时处于睡眠模式后可以恢复网络通信。

于 2017-10-31T19:53:27.503 回答