using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel; using System.Runtime.InteropServices; using DTS.Common.Utilities.Logging; namespace DTS.Common.Utilities { public class PowerManagement { [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 ); [DllImport("powrprof.dll")] static extern uint PowerEnumerate( IntPtr RootPowerKey, IntPtr SchemeGuid, ref Guid SubGroupOfPowerSetting, uint AccessFlags, uint Index, ref Guid Buffer, ref uint BufferSize); private const uint ERROR_MORE_DATA = 234; private static Guid HIGH_PERFORMANCE_GUID = new Guid("8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"); private static Guid MAX_PERFORMANCE_GUID = new Guid("01360e7e-525f-4625-ab94-f283dcfbd515"); //private static Guid GUID_PROCESSOR_SETTINGS_SUBGROUP = new Guid("GUID_PROCESSOR_SETTINGS_SUBGROUP"); //private static Guid GUID_POWERSCHEME_PERSONALITY = new Guid(0x245D8541, 0x3943, 0x4422, 0xB0, 0x25, 0x13, 0xA7, 0x84, 0xF6, 0x79, 0xB7); private static Guid GUID_PROCESSOR_SETTINGS_SUBGROUP = new Guid("54533251-82be-4824-96c1-47b60b740d00"); private const uint ACCESS_INDIVIDUAL_SETTING = 18; public static bool IsInHighPowerMode() { var activeGuidPtr = IntPtr.Zero; try { uint res = 0; //8663 don't do power warning if performance/max performance power modes don't exist //enumerate all the schemes and look for either the high power guid or name, or max //we could use this to determine the active one scheme, but for now we just want to log and //not continue on if we don't find high performance/max performance. var bContainsMaxOrHighPerformance = false; var p = new System.Diagnostics.Process { StartInfo = { UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, WindowStyle = System.Diagnostics.ProcessWindowStyle.Minimized, FileName = "powercfg", Arguments = "/list" } }; p.Start(); var output = p.StandardOutput.ReadToEnd(); //APILogger.Log("Active Power Schemes", output); p.WaitForExit(); if (output.Contains(HIGH_PERFORMANCE_GUID.ToString()) || (output.Contains(MAX_PERFORMANCE_GUID.ToString())) || output.Contains("High performance") || output.Contains("Max performance") ) { bContainsMaxOrHighPerformance = true; } //8663 don't do power warning if performance/max performance power modes don't exist if (!bContainsMaxOrHighPerformance) { return true; } res = PowerGetActiveScheme(IntPtr.Zero, ref activeGuidPtr); if (res != 0) throw new Win32Exception(); var g = (Guid)System.Runtime.InteropServices.Marshal.PtrToStructure(activeGuidPtr, typeof(Guid)); if (g == HIGH_PERFORMANCE_GUID || g == MAX_PERFORMANCE_GUID) { return true; } //Get Friendly Name uint buffSize = 0; var buffer = new StringBuilder(); var subGroupGuid = Guid.Empty; var 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); } var name = buffer.ToString(); name = name.ToLower(); if (name.Contains("maximum performance") || name.Contains("high performance")) { return true; } else { APILogger.Log(string.Format("{0}\nProfile name:", APILogger.GetCurrentMethod()), name, "GUID:", g.ToString()); APILogger.Log("Active Power Schemes", output); return false; } } catch (System.Exception ex) { APILogger.Log(ex); } finally { if (activeGuidPtr != IntPtr.Zero) { var res = LocalFree(activeGuidPtr); if (res != IntPtr.Zero) throw new Win32Exception(); } } //default to okay, so if there's an error, or if we can't read, just continue on return true; } } }