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

16.2k views Asked by At

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.

6

There are 6 answers

0
Jeff Yates On BEST ANSWER

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.

1
Richard Chambers On

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.

1
Fred Stephens On

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.

0
Hugh Allen On

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

1
grettke On

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.

1
aku On

You can monitor Win32_PowerManagementEvent WMI event