2

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?

Simon Kissane
  • 4,373
  • 3
  • 34
  • 59
MoaByter
  • 31
  • 3
  • ExecutionState of what? What Exception? Please read [how-to-ask](https://stackoverflow.com/help/how-to-ask) – nilsK Mar 24 '22 at 14:58
  • Exception: System.EntryPointNotFoundException I want to readout out the Setting of SetThreadExceutionState(...) because I set it with a button. This button hat to be renamed. – MoaByter Mar 24 '22 at 15:13
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Mar 24 '22 at 19:04
  • @MoaByter Your question was not stated clearly. I think I understand what you were asking, so I rewrote it to be clearer. – Simon Kissane Mar 27 '23 at 05:00

1 Answers1

2

SetThreadExecutionState does two different things:

  1. Change the current thread's execution state flags
  2. Reset system-wide idle timers

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, and ES_DISPLAY_REQUIRED tells it to reset the display idle timer. If you don't pass either of ES_SYSTEM_REQUIRED or ES_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, because SetThreadExecutionState(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 has ES_SYSTEM_REQUIRED set, then SetThreadExecutionState(0) == ES_CONTINUOUS|ES_SYSTEM_REQUIRED.

If the function fails, the return value doesn't include ES_CONTINUOUS, it will return 0. 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 with SystemExecutionState information level. If any thread has SetThreadExecutionState(ES_CONTINUOUS|ES_SYSTEM_REQUIRED), then ES_SYSTEM_REQUIRED will be set in the SystemExecutionState. In my own testing, none of the other per-thread execution state flags appear to impact the system execution state.

Simon Kissane
  • 4,373
  • 3
  • 34
  • 59