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?
SetThreadExecutionState
does two different things:It does (1) when you pass in
ES_CONTINUOUS
; otherwise it does (2).So, if you don't pass
ES_CONTINUOUS
as input, it will not change the current thread's execution flags, it will only reset idle timers.When resetting idle timers,
ES_SYSTEM_REQUIRED
tells it to reset the system idle timer, andES_DISPLAY_REQUIRED
tells it to reset the display idle timer. If you don't pass either ofES_SYSTEM_REQUIRED
orES_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
GetThreadExecutionState
you 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_REQUIRED
set, 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
CallNtPowerInformation
withSystemExecutionState
information level. If any thread hasSetThreadExecutionState(ES_CONTINUOUS|ES_SYSTEM_REQUIRED)
, thenES_SYSTEM_REQUIRED
will be set in theSystemExecutionState
. In my own testing, none of the other per-thread execution state flags appear to impact the system execution state.