我需要禁用connected standby模式,直到我的桌面应用程序完成。所需的行为应与通过远程桌面连接到该计算机时发生的行为类似。也就是说,屏幕关闭,但系统在我断开连接之前不会进入睡眠状态。
是否有任何记录或未记录的方法来为我的应用程序获取相同的行为?
我使用PowerRequestExecutionRequired
和/或PowerRequestAwayModeRequired
尝试PowerSetRequest
,但系统仍会在几分钟内进入连接待机模式。我目前使用PowerRequestDisplayRequired
来保持活着,但屏幕始终保持开启状态。
已编辑。这是测试应用程序。按下硬件电源按钮并且屏幕关闭(使用电池运行)后,计时器滴答不超过5分钟。
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CsTestApp
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
this.Load += MainForm_Load;
}
void MainForm_Load(object sender, EventArgs e)
{
// init timer
var timer = new System.Windows.Forms.Timer();
timer.Interval = 1000;
timer.Tick += delegate
{
System.Diagnostics.Trace.WriteLine("CsTestApp: " + DateTime.Now);
};
timer.Start();
// set GUID_EXECUTION_REQUIRED_REQUEST_TIMEOUT
IntPtr pActiveSchemeGuid;
var hr = PowerGetActiveScheme(IntPtr.Zero, out pActiveSchemeGuid);
if (hr != 0)
Marshal.ThrowExceptionForHR((int)hr);
Guid activeSchemeGuid = (Guid)Marshal.PtrToStructure(pActiveSchemeGuid, typeof(Guid));
LocalFree(pActiveSchemeGuid);
int savedTimeout;
hr = PowerReadDCValueIndex(
IntPtr.Zero,
activeSchemeGuid,
GUID_IDLE_RESILIENCY_SUBGROUP,
GUID_EXECUTION_REQUIRED_REQUEST_TIMEOUT,
out savedTimeout);
if (hr != 0)
Marshal.ThrowExceptionForHR((int)hr);
hr = PowerWriteDCValueIndex(
IntPtr.Zero,
activeSchemeGuid,
GUID_IDLE_RESILIENCY_SUBGROUP,
GUID_EXECUTION_REQUIRED_REQUEST_TIMEOUT,
-1);
if (hr != 0)
Marshal.ThrowExceptionForHR((int)hr);
// create power request
var powerRequestContext = new POWER_REQUEST_CONTEXT();
powerRequestContext.Version = POWER_REQUEST_CONTEXT_VERSION;
powerRequestContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
powerRequestContext.SimpleReasonString = "Disable Connected Standby";
var powerRequest = PowerCreateRequest(ref powerRequestContext);
if (powerRequest == IntPtr.Zero)
ThrowLastWin32Error();
// set PowerRequestExecutionRequired
if (!PowerSetRequest(powerRequest, PowerRequestType.PowerRequestExecutionRequired))
ThrowLastWin32Error();
this.FormClosed += delegate
{
timer.Dispose();
PowerClearRequest(powerRequest, PowerRequestType.PowerRequestExecutionRequired);
CloseHandle(powerRequest);
hr = PowerWriteDCValueIndex(
IntPtr.Zero,
activeSchemeGuid,
GUID_IDLE_RESILIENCY_SUBGROUP,
GUID_EXECUTION_REQUIRED_REQUEST_TIMEOUT,
savedTimeout);
if (hr != 0)
Marshal.ThrowExceptionForHR((int)hr);
};
}
// power API interop
static void ThrowLastWin32Error()
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
enum PowerRequestType
{
PowerRequestDisplayRequired = 0,
PowerRequestSystemRequired = 1,
PowerRequestAwayModeRequired = 2,
PowerRequestExecutionRequired = 3,
PowerRequestMaximum
}
[StructLayout(LayoutKind.Sequential)]
struct PowerRequestContextDetailedInformation
{
public IntPtr LocalizedReasonModule;
public UInt32 LocalizedReasonId;
public UInt32 ReasonStringCount;
[MarshalAs(UnmanagedType.LPWStr)]
public string[] ReasonStrings;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct POWER_REQUEST_CONTEXT_DETAILED
{
public UInt32 Version;
public UInt32 Flags;
public PowerRequestContextDetailedInformation DetailedInformation;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct POWER_REQUEST_CONTEXT
{
public UInt32 Version;
public UInt32 Flags;
[MarshalAs(UnmanagedType.LPWStr)]
public string SimpleReasonString;
}
const int POWER_REQUEST_CONTEXT_VERSION = 0;
const int POWER_REQUEST_CONTEXT_SIMPLE_STRING = 0x1;
const int POWER_REQUEST_CONTEXT_DETAILED_STRING = 0x2;
static readonly Guid GUID_IDLE_RESILIENCY_SUBGROUP = new Guid(0x2e601130, 0x5351, 0x4d9d, 0x8e, 0x4, 0x25, 0x29, 0x66, 0xba, 0xd0, 0x54);
static readonly Guid GUID_EXECUTION_REQUIRED_REQUEST_TIMEOUT = new Guid(0x3166bc41, 0x7e98, 0x4e03, 0xb3, 0x4e, 0xec, 0xf, 0x5f, 0x2b, 0x21, 0x8e);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr PowerCreateRequest(ref POWER_REQUEST_CONTEXT Context);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool PowerSetRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool PowerClearRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LocalFree(IntPtr hMem);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerWriteDCValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
int AcValueIndex);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerReadDCValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
out int AcValueIndex);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerGetActiveScheme(IntPtr UserPowerKey, out IntPtr ActivePolicyGuid);
}
}
这是powercfg.exe /requests
的输出:
EXECUTION: [PROCESS] \Device\HarddiskVolume4\Users\avo\Test\CsTestApp.exe Disable Connected Standby
答案 0 :(得分:6)
显然,与PowerRequestExecutionRequired
关联的(记录不佳)超时值会导致“误用”API不会延迟AoAc机器的实际睡眠请求。
在您的情况下,最好的办法是使用PowerWriteACValueIndex
设置超时(-1禁用超时):
ReturnCode = PowerWriteACValueIndex(NULL,
pGuidActivePowerScheme,
&GUID_IDLE_RESILIENCY_SUBGROUP,
&GUID_EXECUTION_REQUIRED_REQUEST_TIMEOUT,
-1);
答案 1 :(得分:4)
这是a similar question, unanswered。我在基于Z3700的平板电脑上尝试PowerSetRequest
/ PowerRequestExecutionRequired
,并且我看到相同的行为,平板电脑在约5分钟内进入连接待机模式,无论此电源请求如何。
网络上关于连接模式内部的信息并不多,但我找到了以下可下载文档:"Introduction to Connected Standby"。以下是关于进入连接待机模式的相关部分:
阶段名称:
连接阶段。<强>描述强>:
系统正在检查远程桌面连接。执行的任务:
•确定是否存在远程桌面会话 •开始跟踪未完成的电力请求。时退出:
没有连接远程桌面会话。...
阶段名称:
桌面活动主持人(DAM)阶段。<强>描述强>:
系统暂停桌面应用程序以减少。执行的任务:
•检查未完成的电源请求(PowerRequestExecutionRequired
) •等待出色的力量 请求将丢弃请求,或强制执行最大值 电池电量超时(5分钟)。退出时:所有未完成的电源请求已被应用程序清除 或达到最大超时时间。他们在连接待机期间的消费。
因此,对于远程连接确实有一些特殊处理,但对于其他服务,您有多达5分钟的时间来完成或暂停PowerRequestExecutionRequired
活动。根据我的经验,即使平板电脑已通电,也会发生这种情况。
IMO,这是一个糟糕的设计决定。它是不 Windows RT平板电脑,它是功能齐全的Windows 8.1 Pro机器,如果我们需要,必须有一种方法可以让它保持活力,至少对于可信任的桌面而言应用
可以disable connected standby mode altogether,但在这种情况下,硬件电源按钮不能用于关闭和打开显示器。
所以,我讨厌成为一个不可能的人,但我认为没有官方方法可以像远程访问守护进程那样禁用连接待机。我希望有人会发表更好的答案。
已更新,此文档还提到了&#34;维护阶段&#34;:
系统执行维护任务。
•等待维护任务完成(如果正在运行)
(交流电源最常见)。
退出时......没有系统维护任务正在运行。
•通常不到1秒。
•系统最有可能阻止交流电源的维护阶段。
也许,可以通过Windows任务计划程序API启动持续维护任务,尽管如果使用电池电源运行,无论如何都无法进入CS模式也不清楚。我没试过这个。
答案 2 :(得分:0)
这可能是最蹩脚的解决方法,但是如果您在后台播放凹槽音乐应用程序,它应该仍然保持您的电脑在其他进程中保持清醒