I maintain a Windows service that runs in session 0. It performs maintenance tasks at certain times in a similar way to the Windows task scheduler. If the system is asleep, it uses SetWaitableTimer() to wake-up. This has worked well for traditional sleep and hibernate for many years.
The widespread adoption of “Modern Standby” has broken this code. Modern standby isn’t a traditional sleep state but rather seems to be a special system idle state. In this state, the OS is still running, services in session 0 are heavily throttled and most other user programs are suspended. Apparently, this increases battery life and gives a phone-like user experience. Interestingly, many built-in OS apps seem to be exempt from the throttled/suspend behaviour.
On a system with modern standby, SetWaitableTimer() fires as normal (although sometimes a little late) and the service code briefly runs again. However, this only lasts a few seconds and then the service is throttled again. The service cannot do any useful work in this brief period.
NB: During this brief period, the screen does not turn on and the OS does not sent a resumed notification.
I have tried the following techniques to fully wake-up the system from this state:
-
Attempt to force system awake. This doesn’t work:
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)
-
Attempt to turn on display using:
SendMessage(hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) -1);
This doesn’t work from a service running in session 0.
- As above but use a proxy process running in the current console session (e.g. not session 0) – This works but the process is launched suspended and doesn’t run until the next time the system is manually resumed. Consequently, this technique doesn’t work either.
Please, is there a way to force the system to fully “wake-up” from modern standby without user intervention?