Event to Detect System Wake Up from Sleep in C#

Event to detect System wake up from sleep in C#

SystemEvents.PowerModeChanged += OnPowerChange;

private void OnPowerChange(object s, PowerModeChangedEventArgs e)
{
switch ( e.Mode )
{
case PowerModes.Resume:
break;
case PowerModes.Suspend:
break;
}
}

You should probably read this:
http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.powermodechanged.aspx

How can I catch an event when the computer resume from sleep/hibernate mode?

SOLVED:

From windows 10, microsoft added Modern Standby that expands the Windows 8.1 Connected Standby power model.
SystemEvents.PowerModeChanged in .net 4.5 only supports Traditional Sleep and Hibernate (S1-4).

From windows 10, version 2004 Modern Standby is forced and cannot be disabled, renders SystemEvents.PowerModeChanged useless in my case.

The new Win32 API for handling Modern Standby power mode changes is referenced here:
PowerRegisterSuspendResumeNotification function MSDN

Unfortunately I didn't managed to find a complete C# implementation for the new API.

Soo I made one myself using C# wrappers for User32.dll and PowrPorf.dll from Vanara Project By dahall (GitHub):

public static class SystemPowerNotifications
{
public static event SystemPowerNotificationEventHandler PowerModeChanged
{
add
{
_powerModeChanged += value;
if (_eventHandler == null)
{
var result = PowrProf.PowerRegisterSuspendResumeNotification(PowrProf.RegisterSuspendResumeNotificationFlags.DEVICE_NOTIFY_CALLBACK,
_dnsp, out _eventHandler);
if (result != Win32Error.ERROR_SUCCESS)
throw new Exception();
}
}
remove
{
_powerModeChanged -= value;
if(_powerModeChanged.GetInvocationList().Length == 0)
{
if (PowrProf.PowerUnregisterSuspendResumeNotification(_eventHandler) != Win32Error.NO_ERROR)
throw new Exception();
_eventHandler.Dispose();
_eventHandler = null;
}
}
}

private static PowrProf.SafeHPOWERNOTIFY _eventHandler;
private static PowrProf.DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS _dnsp = new PowrProf.DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS
{
Callback = OnDeviceNotify,
Context = IntPtr.Zero
};
private static Win32Error OnDeviceNotify(IntPtr context, uint type, IntPtr setting)
{
_powerModeChanged?.Invoke(null,new PowerNotificationArgs((PowerBroadcastType)type));
return 0;
}
private static SystemPowerNotificationEventHandler _powerModeChanged;
}

Full source code:
SystemPowerModeNotification-dotnet4.5 (GitHub)

EDIT:

When using it inside a Windows Service, the callback function registered in PowerRegisterSuspendResumeNotification will fire only when going to Hibernate mode, and not in Modern Standby Sleep/Monitor Off.

There for you need to register to a different notification called RegisterPowerSettingNotification referenced here: Registering for Power Events MSDN
and when a PowerEvent check the monitor state.
Take in mind that it will happen even if the computer will enter Monitor Off/On state without entering sleep mode.

Example of registration:

public static event SystemPowerNotificationEventHandler PowerModeChanged
{
add
{
_powerModeChanged += value;
if (_powerEventHandler == null)
{
if (!string.IsNullOrEmpty(ServiceName))
{
if (_ssh.IsNull)
_ssh = AdvApi32.RegisterServiceCtrlHandlerEx(ServiceName, OnDisplayNotify);
if (_ssh.IsNull)
throw new Exception("Failed To Register ServiceCtrlHandlerEx");
_displayEventHandler = User32.RegisterPowerSettingNotification(((IntPtr)_ssh), PowrProf.GUID_MONITOR_POWER_ON, User32.DEVICE_NOTIFY.DEVICE_NOTIFY_SERVICE_HANDLE);
if (_displayEventHandler.IsNull)
throw new Exception("Failed To Register PowerSettingNotification");
}

var result = PowrProf.PowerRegisterSuspendResumeNotification(PowrProf.RegisterSuspendResumeNotificationFlags.DEVICE_NOTIFY_CALLBACK,
_dnsp, out _powerEventHandler);
if (result != Win32Error.ERROR_SUCCESS)
throw new Exception("Failed To Register PowerSuspendResumeNotification");
}

}
remove
{
_powerModeChanged -= value;
if (_powerModeChanged == null)
{
if (!string.IsNullOrEmpty(ServiceName))
{
if (!User32.UnregisterPowerSettingNotification(_displayEventHandler))
throw new Exception("Failed To Unregister PowerSettingNotification");
_displayEventHandler.Dispose();
_displayEventHandler = null;
}

if (PowrProf.PowerUnregisterSuspendResumeNotification(_powerEventHandler) != Win32Error.NO_ERROR)
throw new Exception("Failed To Unregister PowerSuspendResumeNotification");
_powerEventHandler.Dispose();
_powerEventHandler = null;
}
}
}

Example of the callback:

private static Win32Error OnDisplayNotify(AdvApi32.ServiceControl control,uint eventType,IntPtr eventData,IntPtr context)
{
var dataHandle = new HANDLE(eventData);
var contextHandle = new HANDLE(context);
if(control == AdvApi32.ServiceControl.SERVICE_CONTROL_POWEREVENT)
{
POWERBRODCAST_SETTING settings = (POWERBRODCAST_SETTING)Marshal.PtrToStructure(eventData, typeof(POWERBRODCAST_SETTING));
_powerModeChanged?.Invoke(null, new PowerNotificationArgs((PowerBroadcastType)eventType,settings.Data));
}

return 0;
}

How do I check when the computer is being put to sleep or wakes up?

You can subscribe to the SystemEvents.PowerModeChanged event.

SystemEvents.PowerModeChanged += OnPowerChange;

void OnPowerChange(Object sender, PowerModeChangedEventArgs e) {
switch ( e.Mode ) {
case PowerModes.Resume:
...
case PowerModes.Suspend:
...
}
}


Related Topics



Leave a reply



Submit