1

I have a PC that I access via remote desktop, during specific hours of specific days of the week. It's inconvenient to get to physically, so I want it to wake up on its own and stay awake during those hours, but be able to sleep any other time. I neither need nor want it to "wake on LAN" (mainly because a) I don't want it waking up every time I just open a Windows Explorer window, and b) I have found the "wake on LAN" feature to be finicky and unreliable).

To solve this goal, I have used the powercfg commands via Task Scheduler, as seen in the answer to this question. This almost works; the tasks do in fact correctly change the power scheme as desired. But, the computer goes right back to sleep two minutes later, after waking up to select the "High Performance" scheme, even though that scheme specifically disables sleeping.

What Windows setting do I need to change to get the computer to stay awake after the task runs and sets the "High Performance" scheme as the active power plan?

2 Answers2

3

Windows actually has a second, hidden setting that controls sleep behavior. It's used whenever the computer wakes up for some reason other than the user explicitly doing so, such as when a scheduled task has been configured to wake the computer when it runs. The default value for this setting is 2 Minutes.

This setting can be changed in the "Power Options" dialog, but only after it's been unhidden. You can accomplish this with this command:

powercfg -attributes SUB_SLEEP 7bc4a2f9-d8fc-4469-b07b-33eb785aaca0 -ATTRIB_HIDE

This tells powercfg to remove the ATTRIB_HIDE attribute from the "Sleep unattended sleep timeout" setting found under the "Sleep" subsection of the settings. That setting's GUID is 7bc4a2f9-d8fc-4469-b07b-33eb785aaca0. Once you've run that command in a command prompt window, the next time you open the "Power Options" dialog, you'll see this setting available:

Power Options dialog

Just change the value to whatever you like, i.e. something long enough to keep the computer awake as long as you want it to stay awake after waking up to run a schedule task. Set the value to 0 Minutes to disable the timeout completely; this will allow the computer to follow whatever the power plan's regular "Sleep after" setting is.

If you ever want to hide the option again, just restore the ATTRIB_HIDE value to the setting:

powercfg -attributes SUB_SLEEP 7bc4a2f9-d8fc-4469-b07b-33eb785aaca0 +ATTRIB_HIDE

2

There is only one correct way of doing this. One NEVER changes settings.

Runs a program preventing sleeping or the display turning off while the program runs. Doesn't affect the screensaver.

For more info see docs https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate

NOTE: Do not use the constant

ES_USER_PRESENT as it will always fail.

From above link

To Use

KeepDisplayOn <commandline of program to run>

KeepSystemOn <commandline of program to run>


@Echo Off

ECHO Three files follow

ECHO PreventSleep.bat

ECHO.

ECHO This file compiles KeepDisplayOn.vb and KeepSystemOn.vb to KeepDisplayOn.exe and KeepSystemOn.exe using the system VB.NET compiler.

ECHO.

ECHO Runs a program preventing sleeping or the display turning off while the program runs

ECHO.

ECHO To Use

ECHO KeepDisplayOn ^<commandline of program to run^>

ECHO KeepSystemOn ^<commandline of program to run^>

ECHO.

C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc "%~dp0\KeepDisplayOn.vb" /out:"%~dp0\KeepDisplayOn.exe" /target:winexe

C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc "%~dp0\KeepSystemOn.vb" /out:"%~dp0\KeepSystemOn.exe" /target:winexe

pause


'KeepSystemOn.vb

imports System.Runtime.InteropServices

Public Module MyApplication

Public Declare UNICODE Function SetThreadExecutionState Lib "Kernel32" (ByVal esFlags as Integer) as Integer

Public Const ES_AWAYMODE_REQUIRED = &h40

Public Const ES_CONTINUOUS = &h80000000

Public Const ES_DISPLAY_REQUIRED = &h2

Public Const ES_SYSTEM_REQUIRED = &h1

Public Const ES_USER_PRESENT = &h4

Public Sub Main ()

    Dim wshshell as Object

    Dim Ret as Integer

    WshShell = CreateObject(&quot;WScript.Shell&quot;)

    Ret = SetThreadExecutionState(ES_Continuous + ES_System_Required + ES_Awaymode_Required)

    WshShell.Run(Command(), , True)

End Sub 

End Module


'KeepDisplayOn.vb

imports System.Runtime.InteropServices

Public Module MyApplication

Public Declare UNICODE Function SetThreadExecutionState Lib "Kernel32" (ByVal esFlags as Integer) as Integer

Public Const ES_AWAYMODE_REQUIRED = &h40

Public Const ES_CONTINUOUS = &h80000000

Public Const ES_DISPLAY_REQUIRED = &h2

Public Const ES_SYSTEM_REQUIRED = &h1

Public Const ES_USER_PRESENT = &h4

Public Sub Main ()

    Dim wshshell as Object

    Dim Ret as Integer

    WshShell = CreateObject(&quot;WScript.Shell&quot;)

    Ret = SetThreadExecutionState(ES_Continuous + ES_Display_Required + ES_Awaymode_Required)

    WshShell.Run(Command(), , True)

End Sub 

End Module


Posted to my repository as well https://winsourcecode.blogspot.com/2020/05/keepdisplayon-runs-program-preventing.html

Mark
  • 854