How to use Power Management Functions (PowerEnuimerate) to get power settings

后端 未结 3 1417
予麋鹿
予麋鹿 2021-01-13 06:08

I need my application to read things like the amount of time the system will wait before shutting off the display, or going to sleep, or going into hibernate. As far as I ca

相关标签:
3条回答
  • 2021-01-13 06:43

    I ran across this post looking for a similar solution and found and corrected a few bugs.

    My IDE (visual studio 2019) required a main function so I had to figure out where thats supposed to be in this rather complex code. Finally I tried renaming GetCurrentPowerEnumerateVistaAPI() to Main(). I have also incorporated @Martijn Spaan fix with a slight change. instead of ref settingGuid add ref videoSettingGuid.

    So now it looks like this and functions as expected:

    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();
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-13 06:44

    I found an example on MSDN for using the PowerEnumerate function in VB.

    I have converted the example to C#, and added the Friendly Name to the output of each Video setting in the loop. You can change the GUID_VIDEO_SUBGROUP to one of the other subgroups to see the other settings.

    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();
                    }
                }
            }
        }
    }
    

    The resulting output from this code:

    Power Settings

    0 讨论(0)
  • 2021-01-13 06:48

    However the accepted answer is still valid, I want to point out there is a bug in it, causing it to enumerate all the default values instead of the actual values.

    When reading AC Values it also requires for the sub group guid to be passed:

    res = PowerReadACValue(IntPtr.Zero, activeGuidPtr, pSubGroup, ref settingGuid, ref type, ref temp, ref size);
    
    0 讨论(0)
提交回复
热议问题