Each scheduled task in Windows has the option to wake the computer out of sleep in order to run. But in order for this feature to work, there is at least one other prerequisite that has to be met, and that is to enable the “Allow Wake Timers” setting on the active power plan.
How would you enable wake timers automatically?
Unfortunately, there isn’t a GPO setting (that I am aware of) that will allow you to easily configure this setting.
Looking at the registry, there is a key which could be used to enable\disable wake timers, but the path depends on the power plan GUID, sleep category GUID, and the wake timer GUID.
HKLM:\SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes\(Power Plan GUID)\(Sleep Category GUID)\(Allow Wake Timer GUID)
ACSettingIndex = 0 or 1 –When plugged in.
DCSettingIndex= 0 or 1 –When running on battery.
Where a value of 1 is enable, and 0 is disable.
Because using the registry requires knowledge of these GUIDs, a more elegant solution would be to use the built-in powercfg.exe utility that is available on all modern copies of Windows. This utility has the ability to gather information from all configured power schemes, and can actually set values for the wake timer setting as well.
More information on powercfg can be found here.
Here is a PowerShell script that uses powercfg.exe to enable the “Allow Wake Timers” setting for all power schemes on a computer. It can be deployed via GPO as a logon\logoff script or by any endpoint management system.
The script is fairly short, so I’ll explain how it works.
1. The first task is to gather the information on all the power schemes configured on the computer. This is done by calling powercfg.exe /LIST, which outputs text similar to the image below.
This text is immediately piped to select-string which creates a list containing each power scheme.
$PowerSchemes = (powercfg.exe /LIST) | Select-String "power scheme guid" -List
The Allow Wake Timers GUID is gathered in a similar manner.
$AllowWakeTimersGUID = ((powercfg.exe /q) | Select-String "(Allow wake timers)").tostring().split(" ") | where {($_.length -eq 36) -and ([guid]$_)}
2. The entire Power scheme list is then passed through a for loop, where each power scheme is reduced to its GUID.
$PowerSchemeGUID = $PowerScheme.tostring().split(" ") | where {($_.length -eq 36) -and ([guid]$_)}
3. Finally, the arguments for powercfg.exe are constructed using the GUIDs. There are two different arguments: one for AC and the other for DC, I assume these correspond to the registry values mentioned earlier. And powercfg.exe is called with these arguments, one after another.
foreach ($PowerScheme in $PowerSchemes) { $PowerSchemeGUID = $PowerScheme.tostring().split(" ") | where {($_.length -eq 36) -and ([guid]$_)} foreach ($Argument in ("/SETDCVALUEINDEX $PowerSchemeGUID SUB_SLEEP $AllowWakeTimersGUID 1","/SETACVALUEINDEX $PowerSchemeGUID SUB_SLEEP $AllowWakeTimersGUID 1")) { Start-Process powercfg.exe -ArgumentList $Argument -Wait -Verb runas -WindowStyle Hidden}}
Conclusion
This script seems to work well on Windows 8.1 and Windows 7, but there are a few things to keep in mind:
First of all, you must run this script (like all scripts on this site) “as administrator”. Otherwise, you will be hit with a barrage of UAC prompts, one for each time powercfg.exe is called.
Secondly, the wake timer setting exists on a per power plan basis. Each power plan: “Balanced”, “Power Saver”, “High Performance”, etc… contains the “Allow Wake Timers” setting. The implication is that while “Allow Wake Timers” may be enabled for one power plan, it could be disabled on another at the same time. The power plan that is active while a computer is put into sleep dictates the machine’s ability to respond to wake timers.
My script enables the Allow Wake Timers setting for all power plans. This way, it doesn’t matter if a different plan becomes active any point in time, the computer will always have the ability to respond to wake timers. If having wake timers enabled for certain power plans, while also having it disabled on others is important for your needs, you will have to edit the script. An easy way to do this is to change the “power scheme guid” string from line 1 to the name of your target power plan(s), such as “Balanced”.
Finally, if you would like to disable wake timers for all power plans on a machine, change the 1’s in the script into 0’s (view line #6 below).
foreach ($Argument in ("/SETDCVALUEINDEX $PowerSchemeGUID SUB_SLEEP $AllowWakeTimersGUID 0","/SETACVALUEINDEX $PowerSchemeGUID SUB_SLEEP $AllowWakeTimersGUID 0")) {
Script(s) Used in This Post:
Enable Wake Timers (//adameyob.com/scripts/enable-wake-timers/)
Hi Adam, This is exact what I`m looking for! But I get an error when running the script as administrator: You cannot call a method on a null-valued expression. At C:\Temp\PowerSettings.ps1:2 char:90 + $AllowWakeTimersGUID = ((powercfg.exe /q) | Select-String “(Allow wake timers)”).tostring <<<< ().split(" ") | where {($_.length -eq 36) -and ([guid]$_)} + CategoryInfo : InvalidOperation: (tostring:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull You cannot call a method on a null-valued expression. At C:\Temp\PowerSettings.ps1:5 char:41 + $PowerSchemeGUID = $PowerScheme.tostring <<<< ().split(" ") | where {($_.length -eq 36) -and ([guid]$_)} + CategoryInfo : InvalidOperation: (tostring:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull… Read more »
What’s happening is on line 2, when we run “powercfg.exe /q” your outputted data does not contain any text with “(Allow wake timers)” in there. This is weird. Are you running Windows 10? I have only tested this on 7 and 8.
Do me a favor, open up cmd and run powercfg.exe /q and copy the text and reply to this post or email it to me.
thanks Peter!
Hi Adam,
When I run powercfg.exe /q from cmd I get a lot of information, and the descriptions are in Dutch, so I don`t see Allow wake timers. I think I have to replace that by the Dutch word.
Kind Regards
That’s exactly correct. This became my suspicion once I saw your .dl tld. I did a google translate and found toestaan wake timers as a transaltion in dutch. So to make this work for you, replace line 2 with:
$AllowWakeTimersGUID = ((powercfg.exe /q) | Select-String “(Allow wake timers)”,”(toestaan wake timers)”).tostring().split(” “) | where {($_.length -eq 36) -and ([guid]$_)}
This will work for both Dutch and English based Windows installations.
Thanks for commenting!
If you’re not worried about users having custom power plans, you can use powercfg.exe to set all the default power plans to allow wake timers using the friendly names for the GUIDs.
It would look like:
powercfg /SETACINDEXVALUE SCHEME_BALANCED SUB_SLEEP RTCWake 1
powercfg /SETACINDEXVALUE SCHEME_MIN SUB_SLEEP RTCWake 1
powercfg /SETACINDEXVALUE SCHEME_MAX SUB_SLEEP RTCWake 1
(I only did it for when the machines are on AC, but you could also use /SETDCINDEXVALUE this way.)
Right, but the point of the script is to take the shotgun approach. What I wrote should work under any circumstance, so long as you are using an english version of Windows. So if things were to change later on down the road, the script will still be valid. Whereas with your suggestion, if the power scheme were to change names, then you would have to remember to go back and edit your script.
This script doesn’t modify the Wake Timers setting in Win10. Any ideas as to how to modify your script to support Win10, or any leads as to where to look?
Hey Scott, thanks for visiting my corner of the internet. I just ran my script against a Windows 10 box. It does work for me. I double checked by changing the 1s to 0s, and it changed waketimers back to disabled as well. So it definitely should work. It has occurred to me that this page is by far the most visited on my site, and that a lot of people are interested in how to do this, though they do not know how to run powershell scripts. Please make sure that you are familiar with the requirements to run… Read more »
Hey there Adam,
Thanks for sharing your script. It saved me quite a bit of work and it was well put together.
I do know how to execute PowerShell scripts. I am trying to mass deploy a wake event to a school that utilizes laptop carts, to have them turn on at a certain time for software deployment and patching.
[cid:image002.png@01D1805A.7C7D6660]
The test Win10 machine I am using does not apply the settings. I wonder what’s different between this win10 machine and yours that’s making the success vary…
Thanks.
Thanks for the reply. In the end I spun up a Win10 VM and it works. Not sure why it wasn’t working on the laptop, but all is well. Thanks!
Here’s another option to enable wake timers on AC for the active power plan:
FOR /f “tokens=1,2,3,4” %%I IN (‘powercfg.exe /getactivescheme’) DO ( SET GUID=%%L )
powercfg /setacvalueindex %GUID% SUB_SLEEP RTCWAKE 1
Thanks for the comment. I don’t have time to run this, but it looks like this only works for the AC value on the active scheme. My script works on all the schemes for both DC and AC, hence mine should work on any machine, anywhere on all schemes, so long as it is an english version of windows. But your solution could work depending on the need. Thanks for the input.