当我的程序运行时,防止 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 进入睡眠状态?的主要内容,如果未能解决你的问题,请参考以下文章
如何防止 Android 设备从 Qt 应用程序进入睡眠状态