5

我需要我的应用程序读取诸如系统在关闭显示器、进入睡眠状态或进入休眠状态之前将等待的时间。据我所知,我需要使用电源管理功能(http://msdn.microsoft.com/en-us/library/aa373163%28v=vs.85%29.aspx)特别是,它看起来像我需要使用 PowerEnumerate 方法(http://msdn.microsoft.com/en-us/library/aa372730%28v=vs.85%29.aspx)。

我真的很困惑如何做到这一点。首先,我在 C# 中执行此操作,代码看起来是 C++。其次,C++ 代码似乎并没有真正告诉您如何具体阅读我想要的不同超时。

请注意,我是 Windows 编程和 C# 的新手。我的大部分经验都是在 Java 和 Android 方面。

谢谢

4

3 回答 3

12

在 MSDN 上PowerEnumerate找到了一个在 VB中使用该函数的示例。

我已将该示例转换为 C#,并将友好名称添加到循环中每个视频设置的输出中。您可以将 更改为GUID_VIDEO_SUBGROUP其他子组之一以查看其他设置。

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace TestProject
{
    class PowerEnumerator
    {
        private static Guid NO_SUBGROUP_GUID = new Guid("fea3413e-7e05-4911-9a71-700331f1c294");
        private static Guid GUID_DISK_SUBGROUP = new Guid("0012ee47-9041-4b5d-9b77-535fba8b1442");
        private static Guid GUID_SYSTEM_BUTTON_SUBGROUP = new Guid("4f971e89-eebd-4455-a8de-9e59040e7347");
        private static Guid GUID_PROCESSOR_SETTINGS_SUBGROUP = new Guid("54533251-82be-4824-96c1-47b60b740d00");
        private static Guid GUID_VIDEO_SUBGROUP = new Guid("7516b95f-f776-4464-8c53-06167f40cc99");
        private static Guid GUID_BATTERY_SUBGROUP = new Guid("e73a048d-bf27-4f12-9731-8b2076e8891f");
        private static Guid GUID_SLEEP_SUBGROUP = new Guid("238C9FA8-0AAD-41ED-83F4-97BE242C8F20");
        private static Guid GUID_PCIEXPRESS_SETTINGS_SUBGROUP = new Guid("501a4d13-42af-4429-9fd1-a8218c268e20");

        [DllImport("powrprof.dll")]
        static extern uint PowerEnumerate(
            IntPtr RootPowerKey,
            IntPtr SchemeGuid,
            ref Guid SubGroupOfPowerSetting,
            uint AccessFlags,
            uint Index,
            ref Guid Buffer,
            ref uint BufferSize);

        [DllImport("powrprof.dll")]
        static extern uint PowerGetActiveScheme(
            IntPtr UserRootPowerKey,
            ref IntPtr ActivePolicyGuid);

        [DllImport("powrprof.dll")]
        static extern uint PowerReadACValue(
            IntPtr RootPowerKey,
            IntPtr SchemeGuid,
            IntPtr SubGroupOfPowerSettingGuid,
            ref Guid PowerSettingGuid,
            ref int Type,
            ref IntPtr Buffer,
            ref uint BufferSize
            );

        [DllImport("powrprof.dll", CharSet = CharSet.Unicode)]
        static extern uint PowerReadFriendlyName(
            IntPtr RootPowerKey,
            IntPtr SchemeGuid,
            IntPtr SubGroupOfPowerSettingGuid,
            IntPtr PowerSettingGuid,
            StringBuilder Buffer,
            ref uint BufferSize
            );

        [DllImport("kernel32.dll")]
        static extern IntPtr LocalFree(
            IntPtr hMem
            );

        private const uint ERROR_MORE_DATA = 234;

        public static void GetCurrentPowerEnumerateVistaAPI()
        {
            IntPtr activeGuidPtr = IntPtr.Zero;
            try
            {
                uint res = PowerGetActiveScheme(IntPtr.Zero, ref activeGuidPtr);
                if (res != 0)
                    throw new Win32Exception();

                //Get Friendly Name
                uint buffSize = 0;
                StringBuilder buffer = new StringBuilder();
                Guid subGroupGuid = Guid.Empty;
                Guid powerSettingGuid = Guid.Empty;
                res = PowerReadFriendlyName(IntPtr.Zero, activeGuidPtr,
                    IntPtr.Zero, IntPtr.Zero, buffer, ref buffSize);

                if (res == ERROR_MORE_DATA)
                {
                    buffer.Capacity = (int)buffSize;
                    res = PowerReadFriendlyName(IntPtr.Zero, activeGuidPtr,
                        IntPtr.Zero, IntPtr.Zero, buffer, ref buffSize);
                }

                if (res != 0)
                    throw new Win32Exception();

                Console.WriteLine("ReadFriendlyName = " +
                    buffer.ToString());

                //Get the Power Settings
                Guid VideoSettingGuid = Guid.Empty;
                uint index = 0;
                uint BufferSize = Convert.ToUInt32(Marshal.SizeOf(typeof(Guid)));

                while (
                    PowerEnumerate(IntPtr.Zero, activeGuidPtr, ref GUID_VIDEO_SUBGROUP,
                    18, index, ref VideoSettingGuid, ref BufferSize) == 0)
                {
                    uint size = 4;
                    IntPtr temp = IntPtr.Zero;
                    int type = 0;
                    res = PowerReadACValue(IntPtr.Zero, activeGuidPtr, IntPtr.Zero,
                        ref VideoSettingGuid, ref type, ref temp, ref size);

                    IntPtr pSubGroup = Marshal.AllocHGlobal(Marshal.SizeOf(GUID_VIDEO_SUBGROUP));
                    Marshal.StructureToPtr(GUID_VIDEO_SUBGROUP, pSubGroup, false);
                    IntPtr pSetting = Marshal.AllocHGlobal(Marshal.SizeOf(VideoSettingGuid));
                    Marshal.StructureToPtr(VideoSettingGuid, pSetting, false);

                    uint builderSize = 200;
                    StringBuilder builder = new StringBuilder((int)builderSize);
                    res = PowerReadFriendlyName(IntPtr.Zero, activeGuidPtr,
                        pSubGroup, pSetting, builder, ref builderSize);
                    Console.WriteLine(builder.ToString() + " = " + temp.ToString());

                    index++;
                }
            }
            finally
            {
                if (activeGuidPtr != IntPtr.Zero)
                {
                    IntPtr res = LocalFree(activeGuidPtr);
                    if (res != IntPtr.Zero)
                        throw new Win32Exception();
                }
            }
        }
    }
}

此代码的结果输出:

电源设置

于 2013-04-15T22:25:19.700 回答
1

但是接受的答案仍然有效,我想指出其中存在一个错误,导致它枚举所有默认值而不是实际值。

读取 AC 值时,还需要传递子组 guid:

res = PowerReadACValue(IntPtr.Zero, activeGuidPtr, pSubGroup, ref settingGuid, ref type, ref temp, ref size);
于 2019-01-06T15:11:31.850 回答
0

我跑过这篇文章寻找类似的解决方案,并发现并纠正了一些错误。

我的 IDE(visual studio 2019)需要一个 main 函数,所以我必须弄清楚这个相当复杂的代码应该在哪里。最后我尝试重命名GetCurrentPowerEnumerateVistaAPI()Main(). 我还加入了@Martijn Spaan 修复程序,稍作改动。而不是ref settingGuid添加ref videoSettingGuid.

所以现在它看起来像这样并且按预期运行:

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace TestProject
{
    class PowerEnumerator
    {
        private static Guid NO_SUBGROUP_GUID = new Guid("fea3413e-7e05-4911-9a71-700331f1c294");
        private static Guid GUID_DISK_SUBGROUP = new Guid("0012ee47-9041-4b5d-9b77-535fba8b1442");
        private static Guid GUID_SYSTEM_BUTTON_SUBGROUP = new Guid("4f971e89-eebd-4455-a8de-9e59040e7347");
        private static Guid GUID_PROCESSOR_SETTINGS_SUBGROUP = new Guid("54533251-82be-4824-96c1-47b60b740d00");
        private static Guid GUID_VIDEO_SUBGROUP = new Guid("7516b95f-f776-4464-8c53-06167f40cc99");
        private static Guid GUID_BATTERY_SUBGROUP = new Guid("e73a048d-bf27-4f12-9731-8b2076e8891f");
        private static Guid GUID_SLEEP_SUBGROUP = new Guid("238C9FA8-0AAD-41ED-83F4-97BE242C8F20");
        private static Guid GUID_PCIEXPRESS_SETTINGS_SUBGROUP = new Guid("501a4d13-42af-4429-9fd1-a8218c268e20");

        [DllImport("powrprof.dll")]
        static extern uint PowerEnumerate(
            IntPtr RootPowerKey,
            IntPtr SchemeGuid,
            ref Guid SubGroupOfPowerSetting,
            uint AccessFlags,
            uint Index,
            ref Guid Buffer,
            ref uint BufferSize);

        [DllImport("powrprof.dll")]
        static extern uint PowerGetActiveScheme(
            IntPtr UserRootPowerKey,
            ref IntPtr ActivePolicyGuid);

        [DllImport("powrprof.dll")]
        static extern uint PowerReadACValue(
            IntPtr RootPowerKey,
            IntPtr SchemeGuid,
            IntPtr SubGroupOfPowerSettingGuid,
            ref Guid PowerSettingGuid,
            ref int Type,
            ref IntPtr Buffer,
            ref uint BufferSize
            );

        [DllImport("powrprof.dll", CharSet = CharSet.Unicode)]
        static extern uint PowerReadFriendlyName(
            IntPtr RootPowerKey,
            IntPtr SchemeGuid,
            IntPtr SubGroupOfPowerSettingGuid,
            IntPtr PowerSettingGuid,
            StringBuilder Buffer,
            ref uint BufferSize
            );

        [DllImport("kernel32.dll")]
        static extern IntPtr LocalFree(
            IntPtr hMem
            );

        private const uint ERROR_MORE_DATA = 234;

        public static void Main()
        //public static void GetCurrentPowerEnumerateVistaAPI()
        {
            IntPtr activeGuidPtr = IntPtr.Zero;
            try
            {
                uint res = PowerGetActiveScheme(IntPtr.Zero, ref activeGuidPtr);
                if (res != 0)
                    throw new Win32Exception();

                //Get Friendly Name
                uint buffSize = 0;
                StringBuilder buffer = new StringBuilder();
                Guid subGroupGuid = Guid.Empty;
                Guid powerSettingGuid = Guid.Empty;
                res = PowerReadFriendlyName(IntPtr.Zero, activeGuidPtr,
                    IntPtr.Zero, IntPtr.Zero, buffer, ref buffSize);

                if (res == ERROR_MORE_DATA)
                {
                    buffer.Capacity = (int)buffSize;
                    res = PowerReadFriendlyName(IntPtr.Zero, activeGuidPtr,
                        IntPtr.Zero, IntPtr.Zero, buffer, ref buffSize);
                }

                if (res != 0)
                    throw new Win32Exception();

                Console.WriteLine("ReadFriendlyName = " +
                    buffer.ToString());

                //Get the Power Settings
                Guid VideoSettingGuid = Guid.Empty;
                uint index = 0;
                uint BufferSize = Convert.ToUInt32(Marshal.SizeOf(typeof(Guid)));

                while (
                    PowerEnumerate(IntPtr.Zero, activeGuidPtr, ref GUID_VIDEO_SUBGROUP,
                    18, index, ref VideoSettingGuid, ref BufferSize) == 0)
                {
                    uint size = 4;
                    IntPtr temp = IntPtr.Zero;
                    int type = 0;

                    // My chenges
                    IntPtr pSubGroup = Marshal.AllocHGlobal(Marshal.SizeOf(GUID_VIDEO_SUBGROUP));
                    res = PowerReadACValue(IntPtr.Zero, activeGuidPtr, pSubGroup, ref VideoSettingGuid, ref type, ref temp, ref size);
                    // end my changes

                    Marshal.StructureToPtr(GUID_VIDEO_SUBGROUP, pSubGroup, false);
                    IntPtr pSetting = Marshal.AllocHGlobal(Marshal.SizeOf(VideoSettingGuid));
                    Marshal.StructureToPtr(VideoSettingGuid, pSetting, false);

                    uint builderSize = 200;
                    StringBuilder builder = new StringBuilder((int)builderSize);
                    res = PowerReadFriendlyName(IntPtr.Zero, activeGuidPtr,
                        pSubGroup, pSetting, builder, ref builderSize);
                    Console.WriteLine(builder.ToString() + " = " + temp.ToString());

                    index++;
                }
            }
            finally
            {
                if (activeGuidPtr != IntPtr.Zero)
                {
                    IntPtr res = LocalFree(activeGuidPtr);
                    if (res != IntPtr.Zero)
                        throw new Win32Exception();
                }
            }
            Console.ReadLine();
        }
    }
}
于 2019-07-08T19:20:34.837 回答