24

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.

Bergi
  • 513,640
  • 108
  • 821
  • 1,164
Chris Thompson
  • 14,633
  • 9
  • 40
  • 57
  • For new readers - note that there is a new S0 power mode state (Modern Standby) for which all solutions suggested here do not work: https://docs.microsoft.com/en-us/windows/desktop/power/system-power-states#sleep-state-modern-standby (will update an answer once I get one) – Oded Ben Dov Apr 14 '19 at 12:37

6 Answers6

20

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.

Jeff Yates
  • 58,658
  • 18
  • 135
  • 183
6

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

Hugh Allen
  • 6,247
  • 1
  • 29
  • 43
3

You can monitor Win32_PowerManagementEvent WMI event

aku
  • 115,356
  • 31
  • 164
  • 200
3

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.

grettke
  • 1,397
  • 6
  • 10
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.

Community
  • 1
  • 1
Richard Chambers
  • 14,509
  • 3
  • 62
  • 86
  • +1 Didn't know about connected standby and wondered why my windows service misbehaved on a tablet. Thank you very much! – ur. Apr 28 '16 at 14:13
0

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.