How can I know when Windows is going into/out of sleep or Hibernate mode?

14,236

Solution 1

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.

Solution 2

In .NET, use the PowerModeChanged event. In Win32, use the WM_POWERBROADCAST message.

Solution 3

In a Visual Studio 2005 C++ MFC application you will need to add an ON_MESSAGE() to your message map looking for the WM_POWERBROADCAST message as in this example:

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()

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:

// 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;
}

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:

PBT_APMSUSPEND  received

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:

PBT_APMRESUMESUSPEND  received
PBT_APMRESUMEAUTOMATIC  received

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.

Desktop applications typically require no extra work to integrate with connected standby.

The Desktop Activity Moderator (DAM) is the Windows component that pauses all desktop applications and throttles the runtime of third-party system services during connected standby. The purpose of the DAM is to maintain basic software compatibility with existing applications and services, but mitigate their impact on battery life during sleep.

Windows prevents desktop applications from running during any part of connected standby after the DAM phase completes. Windows allows third-party system services to execute in a throttled mode after completing the DAM phase. In this mode, a third-party service can run for no more than one second of wall-clock time every 30 seconds.

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. The SetThreadExecutionState() 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 an UnregisterPowerSettingNotification() function.

An application or service uses the RegisterPowerSettingNotification function to register for notifications. When the corresponding power setting changes, the system sends notifications as follows:

  • An application receives a WM_POWERBROADCAST message with a wParam of PBT_POWERSETTINGCHANGE and an lParam that points to a POWERBROADCAST_SETTING structure.
  • A service receives a call to the HandlerEx callback function it registered by calling the RegisterServiceCtrlHandlerEx function. The lpEventData parameter sent to the HandlerEx callback function points to a POWERBROADCAST_SETTING structure.

In the POWERBROADCAST_SETTING structure, the PowerSetting member contains the GUID that identifies the notification and the Data member contains the new value of the power setting.

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.

Retrieves the power status of the system. The status indicates whether the system is running on AC or DC power, whether the battery is currently charging, how much battery life remains, and if battery saver is on or off.

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.

Solution 4

You can monitor Win32_PowerManagementEvent WMI event

Solution 5

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.

Share:
14,236

Related videos on Youtube

Chris Thompson
Author by

Chris Thompson

I've been a computer hobbiest all my life. I spent one year as a CS major in college, but changed to International Relations after spending 2 years in Mexico. I'm a self-taught programmer. I've taught myself PHP, VB.NET, and C#. I do programming for both work and pleasure. My current pet project is BatteryBar. It's a battery meter for your taskbar. It keeps historical data on your battery to provide you with a very accurate and consistent reading on how long your battery will last.

Updated on July 07, 2021

Comments

  • Chris Thompson
    Chris Thompson almost 3 years

    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.

    • Oded Ben Dov
      Oded Ben Dov about 5 years
      For new readers - note that there is a new S0 power mode state (Modern Standby) for which all solutions suggested here do not work: docs.microsoft.com/en-us/windows/desktop/power/… (will update an answer once I get one)
  • ur.
    ur. about 8 years
    +1 Didn't know about connected standby and wondered why my windows service misbehaved on a tablet. Thank you very much!
  • Yoav Feuerstein
    Yoav Feuerstein about 7 years
    Do you have a code example which works, please? (tried some online examples but they don't seem to fire the event)
  • n0ne
    n0ne over 6 years
    Thank you for mentioning 'CanHandlePowerEvent', that was my issue!