任何阻止Windows 8进入连接待机模式的API?

avo*_*avo 11 .net c# c++ windows winapi

我需要禁用连接待机模式,直到我的桌面应用程序完成.所需的行为应与通过远程桌面连接到该计算机时发生的行为类似.也就是说,屏幕关闭,但系统在我断开连接之前不会进入睡眠状态.

是否有任何记录或未记录的方法来为我的应用程序获得相同的行为?

我试着PowerSetRequestPowerRequestExecutionRequired和/或PowerRequestAwayModeRequired,但系统仍进入连接待机模式在少数分钟.我目前用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是从powercfg.exe /requests以下输出:

EXECUTION:
[PROCESS] \Device\HarddiskVolume4\Users\avo\Test\CsTestApp.exe
Disable Connected Standby

Eri*_*own 6

显然,有一个(差的)记录的超时值与之关联,PowerRequestExecutionRequired因此"误用"API不会延迟AoAc机器的实际睡眠请求.

在你的情况下,最好的办法是PowerWriteACValueIndex用来设置超时(-1禁用超时):

    ReturnCode = PowerWriteACValueIndex(NULL,
                                   pGuidActivePowerScheme,
                                   &GUID_IDLE_RESILIENCY_SUBGROUP,
                                   &GUID_EXECUTION_REQUIRED_REQUEST_TIMEOUT,
                                   -1);
Run Code Online (Sandbox Code Playgroud)

  • @avo - 你差不多了 - 你需要使用[`PowerSetActiveScheme`]设置活动方案(http://msdn.microsoft.com/en-us/library/windows/desktop/aa372758(v = vs.85) ).aspx)对电源方案进行任何更改.(并且不要忘记在完成后恢复超时...) (2认同)