Мне нужно отключить режим ожидания в режиме ожидания, пока мое настольное приложение не закончит. Желаемое поведение должно быть похоже на то, что происходит, когда я подключаюсь к этой машине через Remote Desktop. То есть экран выключается, но система не входит в спящий режим, пока я не отключусь.
Есть ли какой-либо документированный или недокументированный способ получить такое же поведение для моего приложения?
Я попробовал PowerSetRequest
с помощью PowerRequestExecutionRequired
и/или PowerRequestAwayModeRequired
, но система по-прежнему переходит в режим ожидания в нескольких мин. В настоящее время я использую PowerRequestDisplayRequired
, чтобы сохранить его, но экран всегда остается включенным.
EDITED. Это тестовое приложение. Таймер гаснет не более 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