我如何知道 Windows 何时进入/退出睡眠或休眠模式?
是否可以订阅在 Windows 进入或退出睡眠或休眠状态时触发的 Windows 事件?
我需要让我的应用程序知道计算机何时将进入睡眠状态,以进行一些清理,并避免在计算机退出睡眠状态时出现计时问题。
Is it possible to subscribe to a Windows event that fires when Windows is going into or coming out of Sleep or Hibernate state?
I need my application to be made aware when the computer is going to sleep to do some cleanup and avoid timing issues when it comes out of sleep.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以监视 Win32_PowerManagementEvent WMI 事件
You can monitor Win32_PowerManagementEvent WMI event
不确定您想要监视此情况的频率,但如果您在 .NET 中编写服务,您可以覆盖 ServiceBase,将 CanHandlePowerEvent 设置为 true,然后您将通过 PowerBroadcastStatus 枚举收到电源更改通知。
Not sure how often you want to monitor this, but if you write a service in .NET you can override ServiceBase, set CanHandlePowerEvent to true, and then you'll be notified of power changes via the PowerBroadcastStatus enumeration.
在 Visual Studio 2005 C++ MFC 应用程序中,您需要将
ON_MESSAGE()
添加到消息映射中,以查找WM_POWERBROADCAST
消息,如下例所示:然后您需要添加消息处理程序函数以及类定义更改以声明消息处理程序的成员函数,以便您可以检查消息类型的
wParam
变量,如下所示:我所看到的是在调试器中启动的 Windows 7 上运行的应用程序中使用上述内容进行测试,然后我手动使运行该应用程序的电脑进入睡眠状态,我将看到以下消息:
然后,当电脑重新启动并且我登录时将在调试器输出窗口中看到一条接一条的两条消息:
到目前为止我发现的所有内容都表明您没有任何迹象表明您是从睡眠状态还是休眠状态中出来。 我仍在进一步研究文件和设备句柄在暂停或恢复时需要做什么。 我看到有迹象表明 COM 端口的文件句柄在恢复后不再有效。 我也不确定与其他进程的接口,例如数据库连接。
除了标准的睡眠和休眠电源管理状态之外,Microsoft 还引入了 Windows 8 和 8.1 的连接待机电源状态 根据应用程序的类型,它会产生一些应用程序设计影响。
优雅的艺术Intel 的 Lynn Merrill 的《应用程序暂停》提供了一些有关处理与 Windows 下的电源管理相关的各种 Windows 消息类型的信息,但是日期是 2005 年,因此并非所有材料都与 Windows XP 之后的 Windows 相关。 本文档中描述的消息序列中至少有一条不再使用的消息,从 Windows Vista 开始,Windows 不再使用用于请求应用程序是否能够挂起的
PBT_APMQUERYSUSPEND
消息。SetThreadExecutionState()
函数现在用于指示线程不能因更改为睡眠或休眠状态而中断。 请参阅 stackoverflow 无法捕获睡眠挂起消息 (winxp) 中的答案有关电源管理状态消息更改的详细信息。自 Windows XP 以来的系统电源状态事件
自 Windows XP 以来,Microsoft 改进了电源管理,因为各个版本的 Windows 操作系统共享更多组件,并且 Windows 版本现在部署在电池较小的设备上,需要更小心的电源管理。 请参阅注册电源事件。 同时存在
RegisterPowerSettingNotification()
函数和UnregisterPowerSettingNotification()
函数。另请参阅电源管理功能了解列表自 Windows Vista 以来 Windows API 中的电源管理功能。
系统电源状态和电池状况
您可以使用 Windows 系统服务 API 函数
GetSystemPowerStatus()
检索当前电源状态。但请注意,
SYSTEM_POWER_STATUS
结构中返回的信息是有关电池状态和 AC/DC 电源的信息,而不是实际的设备电源状态(例如睡眠或休眠)。如果 Windows 设备处于睡眠或休眠状态,您的应用程序将不会运行,因此该函数无法用于确定当前 Windows 电源状态。 我添加此注释是因为它对于在研究此主题时看到此帖子的人可能有用。
In a Visual Studio 2005 C++ MFC application you will need to add an
ON_MESSAGE()
to your message map looking for theWM_POWERBROADCAST
message as in this example:Then you will need to add the message handler function along with the class definition change to declare the member function for the message handler so that you can check the
wParam
variable for the message type as in this skeleton:What I have seen is that a test using the above in an application running on Windows 7 that is started in the debugger and then I manually make my PC running the application to Sleep I will see the following message:
Then when the PC is restarted and I sign-in what I will see in the debugger output window are two messages one after the other:
Everything that I have found thus far indicates that you have no indication whether you are coming out of a Sleep state or a Hibernate state. I am still doing further research on what needs to be done when suspending or when resuming so far as file and device handles. I have seen indications that file handles to COM ports are no longer valid after resuming. I also am unsure about interfaces to other processes for instance database connections.
In addition to the standard Sleep and Hibernate power management states Microsoft has introduced the Connected Standby power state with Windows 8 and 8.1 which has some application design ramifications depending on the type of application.
The Art of Graceful Application Suspension by Lynn Merrill from Intel has some information about handling the various Windows message types associated with Power Management under Windows however it is date 2005 so not all material may pertain to Windows after Windows XP. There is at least one no longer used message in the message sequence described in this document as beginning with Windows Vista the
PBT_APMQUERYSUSPEND
message which was used to request whether an application was able to suspend is no longer used by Windows. TheSetThreadExecutionState()
function is now used to indicate that a thread can not be interrupted with a change to Sleep or Hibernate state. See the answers in stackoverflow Can't catch sleep suspend messages (winxp) for details on Power Management state message changes.System power state events since Windows XP
Microsoft has improved power management since Windows XP as the various versions of the Windows OS share more components and versions of Windows are now being deployed on smaller devices with battery requiring more careful power management. See Registering for Power Events. There is both a
RegisterPowerSettingNotification()
function and anUnregisterPowerSettingNotification()
function.See also Power Management Functions for the list of the power management functions in the Windows API since Windows Vista.
System power status and battery condition
You can use the Windows System Services API function
GetSystemPowerStatus()
to retrieve the current power status.However note that the information returned in the
SYSTEM_POWER_STATUS
struct is about battery status and AC/DC power source and not the actual device power state such as Sleep or Hibernate.And if the Windows device is in a Sleep or Hibernate state, your application will not be running so this function can not be used to determine the current Windows power state. I include this note as it may be useful for someone who arrives at this post while researching this topic.
Microsoft.Win32.SystemEvents.PowerModeChanged
活动将为您提供此信息。 该事件在 Microsoft 迄今为止发布的 .NET 框架的所有变体中都可用。Microsoft.Win32.SystemEvents.PowerModeChanged
event will give you this information. This event is available in all variants of the .NET framework released by Microsoft so far.在 .NET 中,使用 PowerModeChanged 事件。
在 Win32 中,使用 WM_POWERBROADCAST 消息。
In .NET, use the PowerModeChanged event.
In Win32, use the WM_POWERBROADCAST message.
您可以订阅 NetworkChange.NetworkAvailabilityChanged 和 NetworkChange.NetworkAddressChanged。
我通常会启动一个两秒定时器,以便在超时后可以在处于睡眠模式后恢复网络通信。
You can subscribe to NetworkChange.NetworkAvailabilityChanged and NetworkChange.NetworkAddressChanged.
I generally start a two second timer so that I can resume network communications after being in sleep mode when it times out.