当我的程序运行时,防止 Windows 进入睡眠状态?

Posted

技术标签:

【中文标题】当我的程序运行时,防止 Windows 进入睡眠状态?【英文标题】:Prevent windows from going into sleep when my program is running? 【发布时间】:2010-10-12 08:52:12 【问题描述】:

当我的程序运行时,我必须阻止 Windows 进入睡眠状态。

而且我不仅想阻止睡眠定时器,如果我按下睡眠按钮或以任何其他方式主动告诉计算机睡眠,我还想取消睡眠事件。因此 SetThreadExecutionState 是不够的。

或者...我实际上不必完全阻止睡眠,只需延迟 5-10 秒以让我的程序完成任务。

(我知道这是不好的程序行为,但仅供个人使用。)

【问题讨论】:

【参考方案1】:

考虑过vim's answer

"使用 PowerCreateRequest、PowerSetRequest 和 PowerClearRequest 函数是首选方法。”

在msdn 上链接的AvailabilityRequests.docx 很难进入(阅读太多),我在网上搜索了c# 中基于PowerCreateRequest 并找到@987654324 的具体示例@ [EDIT 2016 - 不再可用]

根据我的需要复制并调整它(从 msdn 复制的 CloseHandle 的 PInvoke):

using System.Runtime.InteropServices;

    #region prevent screensaver, display dimming and automatically sleeping
    POWER_REQUEST_CONTEXT _PowerRequestContext;
    IntPtr _PowerRequest; //HANDLE

    // Availability Request Functions
    [DllImport("kernel32.dll")]
    static extern IntPtr PowerCreateRequest(ref POWER_REQUEST_CONTEXT Context);

    [DllImport("kernel32.dll")]
    static extern bool PowerSetRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);

    [DllImport("kernel32.dll")]
    static extern bool PowerClearRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    internal static extern int CloseHandle(IntPtr hObject);

    // Availablity Request Enumerations and Constants
    enum PowerRequestType
    
        PowerRequestDisplayRequired = 0,
        PowerRequestSystemRequired,
        PowerRequestAwayModeRequired,
        PowerRequestMaximum
    

    const int POWER_REQUEST_CONTEXT_VERSION = 0;
    const int POWER_REQUEST_CONTEXT_SIMPLE_STRING = 0x1;
    const int POWER_REQUEST_CONTEXT_DETAILED_STRING = 0x2;

    // Availablity Request Structures
    // Note:  Windows defines the POWER_REQUEST_CONTEXT structure with an
    // internal union of SimpleReasonString and Detailed information.
    // To avoid runtime interop issues, this version of 
    // POWER_REQUEST_CONTEXT only supports SimpleReasonString.  
    // To use the detailed information,
    // define the PowerCreateRequest function with the first 
    // parameter of type POWER_REQUEST_CONTEXT_DETAILED.
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct POWER_REQUEST_CONTEXT
    
        public UInt32 Version;
        public UInt32 Flags;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string
            SimpleReasonString;
    

    [StructLayout(LayoutKind.Sequential)]
    public struct PowerRequestContextDetailedInformation
    
        public IntPtr LocalizedReasonModule;
        public UInt32 LocalizedReasonId;
        public UInt32 ReasonStringCount;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string[] ReasonStrings;
    

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct POWER_REQUEST_CONTEXT_DETAILED
    
        public UInt32 Version;
        public UInt32 Flags;
        public PowerRequestContextDetailedInformation DetailedInformation;
    
    #endregion



    /// <summary>
    /// Prevent screensaver, display dimming and power saving. This function wraps PInvokes on Win32 API. 
    /// </summary>
    /// <param name="enableConstantDisplayAndPower">True to get a constant display and power - False to clear the settings</param>
    private void EnableConstantDisplayAndPower(bool enableConstantDisplayAndPower)
    
        if (enableConstantDisplayAndPower)
        
            // Set up the diagnostic string
            _PowerRequestContext.Version = POWER_REQUEST_CONTEXT_VERSION;
            _PowerRequestContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
            _PowerRequestContext.SimpleReasonString = "Continuous measurement"; // your reason for changing the power settings;

            // Create the request, get a handle
            _PowerRequest = PowerCreateRequest(ref _PowerRequestContext);

            // Set the request
            PowerSetRequest(_PowerRequest, PowerRequestType.PowerRequestSystemRequired);
            PowerSetRequest(_PowerRequest, PowerRequestType.PowerRequestDisplayRequired);
        
        else
        
            // Clear the request
            PowerClearRequest(_PowerRequest, PowerRequestType.PowerRequestSystemRequired);
            PowerClearRequest(_PowerRequest, PowerRequestType.PowerRequestDisplayRequired);

            CloseHandle(_PowerRequest);
        
    

【讨论】:

这个方法很好,因为当你运行 powercfg /requests 时,你给出的系统不休眠等原因会显示出来。这将有助于用户诊断睡眠问题 具有讽刺意味的是,一个名为 webhost4life 的网站已经死了。 POWER_REQUEST_CONTEXT 结构实际上应该在末尾有两个额外的 IntPtr 字段来填充它,以便在详细情况下它与最小大小一样大。【参考方案2】:

我在通过 USB 连接的硬件设备上遇到了这样的问题。 XP /Vista 会在...中间休眠/休眠... 太好了,当它恢复时它可以继续。如果硬件仍然连接!!! 用户有随时拉电缆的习惯。

你需要处理 XP 和 Vista

在 XP 下捕获 WM_POWERBROADCAST 并查找 PBT_APMQUERYSUSPEND wparam。

   // See if bit 1 is set, this means that you can send a deny while we are busy
   if (message.LParam & 0x1)
   
      // send the deny message
      return BROADCAST_QUERY_DENY;
    // if
   else
   
      return TRUE;
    // else

Vista下这样使用SetThreadExecutionState

// try this for vista, it will fail on XP
if (SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED) == NULL)

   // try XP variant as well just to make sure 
   SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
  // if 

当您的应用完成后,将其恢复正常

// set state back to normal
SetThreadExecutionState(ES_CONTINUOUS);

【讨论】:

嗯,我错了,SetThreadExecutionState 确实有效,只需要设置 ES_AWAYMODE_REQUIRED 即可。奇怪的是我的显示器变黑了,但系统从未完全进入睡眠状态。 这就是离开模式的意义所在。这个想法是计算机通常会处于睡眠状态,因此它看起来像是在睡觉。然后当后台任务完成时(例如录制电视节目),应用程序会关闭所需的系统和离开模式位,并且计算机实际上会进入睡眠状态。 >奇怪的是,我的显示器黑屏了,但系统从未完全进入睡眠状态——也许这只是默认的空白屏幕保护程序? 这里是 Window Message 的链接,可以帮助任何人通过 google 保存:msdn.microsoft.com/en-us/library/windows/desktop/… SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); 是否适用于 WinXP?【参考方案3】:

使用 PowerCreateRequest、PowerSetRequest 和 PowerClearRequest 函数是首选方法。详细信息和示例代码(C/C#)在http://msdn.microsoft.com/en-us/library/windows/hardware/gg463205.aspx 内

【讨论】:

【参考方案4】:

set wsc = CreateObject("WScript.Shell")

做 WScript.Sleep (60*1000) wsc.SendKeys ("SCROLLLOCK 2") 循环

-将以上代码放入记事本中,将文件另存为.vbs并双击文件

【讨论】:

【参考方案5】:

应使用与防止屏幕保护程序相同的技术。见Programmatically prevent Windows screensaver from starting。

请注意,某些安全设置可以覆盖此设置(强制计算机在一定时间后锁定是一)。

【讨论】:

【参考方案6】:

如果它进入睡眠状态,如何唤醒它?

http://www.enterprisenetworksandservers.com/monthly/art.php?1049

【讨论】:

不可能,我必须在计算机进入睡眠状态之前禁用 wifi 设备。否则,当我再次唤醒计算机时,设备将无法使用。英特尔的 win7 驱动程序很慢 :(【参考方案7】:

以下是我尝试使用现代电源可用性请求 API(取代 SetThreadExecutionState),作为 suggested by vim。

我正在使用我遇到的一个不错的 P/Invoke NuGet,Vanara.PInvoke.Kernel32:

using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;

// create request object
using var request = PowerCreateRequest(new REASON_CONTEXT("App FOO is working"));
if (request.IsInvalid)

    throw new InvalidOperationException(
       $"Could not create power availability request: Win32Error.GetLastError()");


// send request
if (!PowerSetRequest(request, POWER_REQUEST_TYPE.PowerRequestSystemRequired))

    throw new InvalidOperationException(
       $"Could not send power availability request: Win32Error.GetLastError()");

    
// do stuff that required the machine to be up
Console.WriteLine("Doing stuff...");
await Task.Delay(5000);

// clear request
if (!PowerClearRequest(request, POWER_REQUEST_TYPE.PowerRequestSystemRequired))

    Console.WriteLine(
      "WARNING: Could not clear power availability request: 0",
      Win32Error.GetLastError());

您可以通过从管理终端发出 powercfg /requests 来查看您的请求。

【讨论】:

【参考方案8】:

如果您需要一个在您的应用程序运行之前应该可以工作的显示器,请尝试设置“ES_DISPLAY_REQUIRED”而不是离开模式:

SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);

完成应用程序后,请确保清除所有其他标志。

SetThreadExecutionState(ES_CONTINUOUS);

【讨论】:

以上是关于当我的程序运行时,防止 Windows 进入睡眠状态?的主要内容,如果未能解决你的问题,请参考以下文章

Linux/Windows 睡眠时间

防止电脑休眠

如何防止 Android 设备从 Qt 应用程序进入睡眠状态

允许计算机在从 Windows 应用程序播放音频时进入睡眠状态

防止睡眠模式

如何防止Mac进入睡眠状态?偷偷告诉你这4个好方法!