On Windows, each thread has an execution state which can be set by calling SetThreadExecutionState. For example, if a thread calls:
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED)
then Windows will not turn off the display, until that thread changes its execution state, or terminates.
It can be accessed from C#:
[DllImport("kernel32.dll", SetLastError = true)] SetThreadExecutionState(...)
But, while SetThreadExecutionState sets the execution state, there doesn't appear to be any equivalent GetThreadExecutionState API. kernel32.dll exports SetThreadExecutionState but not GetThreadExecutionState. I tried:
[DllImport("kernel32.dll", SetLastError = true)] internal static extern uint GetThreadExecutionState();
But I got a System.EntryPointNotFoundException saying GetThreadExecutionState does not exist in kernel32.dll.
How then can I find out the execution state of the current thread without changing it?
SetThreadExecutionStatedoes two different things:It does (1) when you pass in
ES_CONTINUOUS; otherwise it does (2).So, if you don't pass
ES_CONTINUOUSas input, it will not change the current thread's execution flags, it will only reset idle timers.When resetting idle timers,
ES_SYSTEM_REQUIREDtells it to reset the system idle timer, andES_DISPLAY_REQUIREDtells it to reset the display idle timer. If you don't pass either ofES_SYSTEM_REQUIREDorES_DISPLAY_REQUIRED, it won't reset any idle timers.In other words,
SetThreadExecutionState(0)is essentially a no-op – it doesn't change the thread's execution flags, nor does it reset any idle timers. But it does do something useful – it returns the current value of the thread execution flags.So, the
GetThreadExecutionStateyou were looking for doesn't exist, but you don't need it, becauseSetThreadExecutionState(0)is equivalent.Note that the return value always includes
ES_CONTINUOUS. So, if your thread doesn't have any execution state flags set,SetThreadExecutionState(0) == ES_CONTINUOUS. Whereas, suppose the current thread hasES_SYSTEM_REQUIREDset, thenSetThreadExecutionState(0) == ES_CONTINUOUS|ES_SYSTEM_REQUIRED.If the function fails, the return value doesn't include
ES_CONTINUOUS, it will return0. As far as I am aware, the only way the function can fail, is if you pass some unsupported flag.Note as well as the per-thread execution state flags, there are also system-wide flags. You can get those using
CallNtPowerInformationwithSystemExecutionStateinformation level. If any thread hasSetThreadExecutionState(ES_CONTINUOUS|ES_SYSTEM_REQUIRED), thenES_SYSTEM_REQUIREDwill be set in theSystemExecutionState. In my own testing, none of the other per-thread execution state flags appear to impact the system execution state.