Search code examples
c#windowspower-management

Get Windows power plans/schemes in C# (using WinAPI)


I'm interested in getting all power plans that you have in your computer using C#.

I was thinking you might be able to use the API PowerEnumerate function in some way:

DWORD WINAPI PowerEnumerate(
  _In_opt_   HKEY RootPowerKey,
  _In_opt_   const GUID *SchemeGuid,
  _In_opt_   const GUID *SubGroupOfPowerSettingsGuid,
  _In_       POWER_DATA_ACCESSOR AccessFlags,
  _In_       ULONG Index,
  _Out_opt_  UCHAR *Buffer,
  _Inout_    DWORD *BufferSize
);

But I have no idea on how to, as I really don't know C. How can I enumerate through all available power plans and create a a list of them? I then want to be able to access each power plans GUID and their "user friendly name".


Solution

  • This should do it:

    using System;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Collections.Generic;
    
    public class Program
    {
        [DllImport("PowrProf.dll")]
        public static extern UInt32 PowerEnumerate(IntPtr RootPowerKey, IntPtr SchemeGuid, IntPtr SubGroupOfPowerSettingGuid, UInt32 AcessFlags, UInt32 Index, ref Guid Buffer, ref UInt32 BufferSize);
    
        [DllImport("PowrProf.dll")]
        public static extern UInt32 PowerReadFriendlyName(IntPtr RootPowerKey, ref Guid SchemeGuid, IntPtr SubGroupOfPowerSettingGuid, IntPtr PowerSettingGuid, IntPtr Buffer, ref UInt32 BufferSize);
    
        public enum AccessFlags : uint
        {
            ACCESS_SCHEME = 16,
            ACCESS_SUBGROUP = 17,
            ACCESS_INDIVIDUAL_SETTING = 18
        }
    
        private static string ReadFriendlyName(Guid schemeGuid)
        {
            uint sizeName = 1024;
            IntPtr pSizeName = Marshal.AllocHGlobal((int)sizeName);
    
            string friendlyName;
    
            try
            {
                PowerReadFriendlyName(IntPtr.Zero, ref schemeGuid, IntPtr.Zero, IntPtr.Zero, pSizeName, ref sizeName);
                friendlyName = Marshal.PtrToStringUni(pSizeName);
            }
            finally
            {
                Marshal.FreeHGlobal(pSizeName);
            }
    
            return friendlyName;
        }
    
        public static IEnumerable<Guid> GetAll()
        {
            var schemeGuid = Guid.Empty;
    
            uint sizeSchemeGuid = (uint)Marshal.SizeOf(typeof(Guid));
            uint schemeIndex = 0;
    
            while (PowerEnumerate(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)AccessFlags.ACCESS_SCHEME, schemeIndex, ref schemeGuid, ref sizeSchemeGuid) == 0)
            {
                yield return schemeGuid;
                schemeIndex++;
            }
        }
    
        public static void Main()
        {   
            var guidPlans = GetAll();
    
            foreach (Guid guidPlan in guidPlans)
            {
                Console.WriteLine(ReadFriendlyName(guidPlan));
            }
        }
    }
    

    You might have to run this program as administrator for security purposes.