[英]SetThreadExecutionState is not working when called from windows service
I want prevent system from going to sleep/hibernate from a windows service.我想防止系统从 windows 服务进入睡眠/休眠状态。 I am calling
SetThreadExecutionState
function to do that.我正在调用
SetThreadExecutionState
function 来做到这一点。 But it seems to have no effect.但它似乎没有任何效果。 I just want to know whether the function
SetThreadExecutionState
will for windows services.我只想知道 function
SetThreadExecutionState
是否适用于 windows 服务。 If not what will be the alternative ways to that.如果不是,那将是什么替代方法。
Below is the C# code i am using.下面是我正在使用的 C# 代码。 I am calling it on
Onstart
method of service.我在服务的
Onstart
方法上调用它。
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint SetThreadExecutionState(EXECUTION_STATE esFlags);
private void KeepAlive()
{
SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS)
}
Calling SetThreadExecutionState without ES_CONTINUOUS simply resets the idle timer;
在没有 ES_CONTINUOUS 的情况下调用 SetThreadExecutionState 只会重置空闲计时器; to keep the display or system in the working state, the thread must call SetThreadExecutionState periodically.
为了保持显示或系统在工作 state,线程必须定期调用 SetThreadExecutionState。
You need to call this function every now and then.您需要不时调用此 function。 It's not a fire-and-forget.
这不是一劳永逸。
SetThreadExecutionState is only valid for the thread that calls it. SetThreadExecutionState 仅对调用它的线程有效。 If it's called in a worker thread, even with ES_CONTINUOUS, once the worker thread is dead, the setting is not valid anymore and then screen saver will be on again.
如果在工作线程中调用,即使使用 ES_CONTINUOUS,一旦工作线程死亡,设置将不再有效,然后屏幕保护程序将再次打开。
Calling this API from a Timer will wake up a worker thread before previous thread is dead and therefore makes it work.从 Timer 调用此 API 将在前一个线程死亡之前唤醒一个工作线程,从而使其工作。
So if you call SetThreadExecutionState in your main thread, like UI thread in client applications, you don't need timer.因此,如果您在主线程中调用 SetThreadExecutionState,例如客户端应用程序中的 UI 线程,则不需要计时器。
Here's my solution, hope it helps.这是我的解决方案,希望对您有所帮助。 Seems to work on Windows 10. Usage:
似乎适用于 Windows 10。用法:
PowerUtilities.PreventPowerSave(); PowerUtilities.PreventPowerSave();
... then later ...然后稍后
PowerUtilities.Shutdown(); PowerUtilities.Shutdown();
Not meant to be re-callable.不意味着可以重新调用。
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
namespace KeepAlive
{
public static class PowerUtilities
{
[Flags]
public enum EXECUTION_STATE : uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
// Legacy flag, should not be used.
// ES_USER_PRESENT = 0x00000004
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint SetThreadExecutionState(EXECUTION_STATE esFlags);
private static AutoResetEvent _event = new AutoResetEvent(false);
public static void PreventPowerSave()
{
(new TaskFactory()).StartNew(() =>
{
SetThreadExecutionState(
EXECUTION_STATE.ES_CONTINUOUS
| EXECUTION_STATE.ES_DISPLAY_REQUIRED
| EXECUTION_STATE.ES_SYSTEM_REQUIRED);
_event.WaitOne();
},
TaskCreationOptions.LongRunning);
}
public static void Shutdown()
{
_event.Set();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.