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

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

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

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

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

【问题讨论】:

    标签: windows winapi sleep


    【解决方案1】:

    考虑过vim's answer

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

    msdn 上链接的AvailabilityRequests.docx 很难进入(阅读太多),我在网上搜索了 中基于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);
            

            【讨论】:

              猜你喜欢
              • 2016-04-22
              • 2012-07-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多