【问题标题】:How to use Power Management Functions (PowerEnuimerate) to get power settings如何使用电源管理功能 (PowerEnuimerate) 获取电源设置
【发布时间】:2013-04-08 02:04:56
【问题描述】:

我需要我的应用程序读取诸如系统在关闭显示器、进入睡眠状态或进入休眠状态之前等待的时间。据我所知,我需要使用电源管理功能 (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 方面的。

谢谢

【问题讨论】:

    标签: c# .net windows desktop


    【解决方案1】:

    我找到了一个example on MSDN 用于在VB 中使用PowerEnumerate 函数。

    我已将示例转换为 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();
                    }
                }
            }
        }
    }
    

    此代码的结果输出:

    【讨论】:

    • 看起来我们正在使用一堆 .dll。我在哪里可以找到有关它们的文档?
    • 根据MSDN PowerEnumerate page(见页面底部),powrprof.dll 似乎包含在较新版本的 Windows(Vista 和较新版本)中,并且 kernel32.dll(LocalFree 函数)已成为其中的一部分至少从 XP 开始的 Windows:LocalFree on MSDN
    • 我正在尝试示例代码,但我注意到当我在“电源选项”对话框中更改单个设置时。当我重新运行示例时,它不会反映出来。例如,我在 Balanced 计划中,我将“最小处理器状态”从 5% 更改为 100%,但输出将始终显示 5%。这有什么原因吗?如何获得正确的值?
    【解决方案2】:

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

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

    res = PowerReadACValue(IntPtr.Zero, activeGuidPtr, pSubGroup, ref settingGuid, ref type, ref temp, ref size);
    

    【讨论】:

      【解决方案3】:

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

      我的 IDE(Visual Studio 2019)需要一个主函数,所以我必须弄清楚这个相当复杂的代码应该在哪里。最后我尝试将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();
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2023-01-27
        • 2019-05-02
        • 2011-12-02
        • 2013-02-20
        • 1970-01-01
        • 2019-04-30
        • 2011-01-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多