In my file transfer application (WinSCP), I use SetThreadExecutionState(ES_SYSTEM_REQUIRED)
to prevent the system from going into sleep mode while a file transfer is in progress. But this does not work anymore on Windows 11.
I didn't find any reference about different requirements for an application to prevent sleep mode on Windows 11.
My application is a C Win32 app. But I can reproduce the same problem with a trivial .NET 5 WinForms C# application.
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Label label1;
public enum EXECUTION_STATE : uint
{
ES_SYSTEM_REQUIRED = 0x00000001
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint SetThreadExecutionState(EXECUTION_STATE esFlags);
// The timer ticks every second.
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = (int.Parse(label1.Text) 1).ToString();
SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED);
}
As long as the application is running on Windows 10, the system never goes into sleep mode. But Windows 11 goes to sleep as scheduled.
Windows File Explorer on Windows 11 successfully prevents the sleep while it is transferring files. So it's not like it's not possible to prevent Windows 11 from going into sleep mode.
Why doesn't SetThreadExecutionState(ES_SYSTEM_REQUIRED)
work anymore on Windows 11? Is there a different API on Windows 11 for this task?
CodePudding user response:
According to SetThreadExecutionState,
Calling SetThreadExecutionState without ES_CONTINUOUS simply resets the idle timer; to keep the display or system in the working state, the thread must call SetThreadExecutionState periodically.
Alternatively, Calling SetThreadExecutionState as the document example shows:
// Enable away mode and prevent the sleep idle time-out.
//
SetThreadExecutionState(ES_CONTINUOUS | ES_AWAYMODE_REQUIRED);
//
// ...
//
//
// Clear EXECUTION_STATE flags to disable away mode and allow the system to idle to sleep normally.
//
SetThreadExecutionState(ES_CONTINUOUS);
CodePudding user response:
It seems that the SetThreadExecutionState(ES_SYSTEM_REQUIRED)
"reset the idle timer" API (i.e. without ES_CONTINUOUS
flag) is broken in Windows 11.
The ES_CONTINUOUS
API works. So I had to redesign my application to use that one. As my application can have multiple threads, each doing lengthy operation, repeatedly calling the SetThreadExecutionState(ES_SYSTEM_REQUIRED)
flag was more convenient.
Now I have to have a separate thread whose sole purpose is to report the application state to the system. First time the SetThreadExecutionState(ES_SYSTEM_REQUIRED)
flag would be previously called by any thread now triggers the "state thread" to call SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_CONTINUOUS)
. Further calls just reset an internal 5 seconds timer. If that timer eventually expires, the state thread calls SetThreadExecutionState(ES_CONTINUOUS)