在Windows上,每个线程都有一个执行状态,可以通过调用SetThreadExecutionState
来设置。例如,如果线程调用:
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED)
则在该线程更改其执行状态或终止之前,Windows不会关闭显示。
可以从C#访问:
[DllImport("kernel32.dll", SetLastError = true)] SetThreadExecutionState(...)
但是,当SetThreadExecutionState
设置执行状态时,似乎没有任何等效的GetThreadExecutionState
API。kernel32.dll
导出SetThreadExecutionState
而不导出GetThreadExecutionState
。我试过了:
[DllImport("kernel32.dll", SetLastError = true)] internal static extern uint GetThreadExecutionState();
但我得到了一个System.EntryPointNotFoundException
,说GetThreadExecutionState
在kernel32.dll
中不存在。
那么,我如何在不更改当前线程的情况下找到它的执行状态呢?
SetThreadExecutionState
做两件不同的事情:
- 更改当前线程的执行状态标志
- 重置系统范围内的空闲定时器
当您通过ES_CONTINUOUS
时,它会执行(1(;否则是(2(。
因此,如果不将ES_CONTINUOUS
作为输入传递,它将不会更改当前线程的执行标志,只会重置空闲计时器。
当复位空闲定时器时,ES_SYSTEM_REQUIRED
告诉它复位系统空闲定时器,ES_DISPLAY_REQUIRED
告诉它复位显示器空闲定时器。如果你没有通过ES_SYSTEM_REQUIRED
或ES_DISPLAY_REQUIRED
,它不会重置任何空闲定时器。
换句话说,SetThreadExecutionState(0)
本质上是一个无操作——它不会更改线程的执行标志,也不会重置任何空闲定时器。但它确实做了一些有用的事情——它返回线程执行标志的当前值。
所以,你要找的GetThreadExecutionState
不存在,但你不需要它,因为SetThreadExecutionState(0)
是等价的。
请注意,返回值始终包括ES_CONTINUOUS
。因此,如果您的线程没有设置任何执行状态标志SetThreadExecutionState(0) == ES_CONTINUOUS
。然而,假设当前线程设置了ES_SYSTEM_REQUIRED
,那么SetThreadExecutionState(0) == ES_CONTINUOUS|ES_SYSTEM_REQUIRED
。
如果函数失败,返回值不包括ES_CONTINUOUS
,则返回0
。据我所知,函数失败的唯一方法是传递一些不受支持的标志。
请注意,除了每个线程的执行状态标志外,还有系统范围的标志。您可以使用CallNtPowerInformation
和SystemExecutionState
信息级别来获得这些信息。如果任何线程具有SetThreadExecutionState(ES_CONTINUOUS|ES_SYSTEM_REQUIRED)
,则在SystemExecutionState
中将设置ES_SYSTEM_REQUIRED
。在我自己的测试中,其他每线程执行状态标志似乎都不会影响系统执行状态。