Comment détecter si un système Windows prend en charge les timers

Je dois détecter par programme si mon ordinateur (Windows 7/8) prend en charge les timers. Jusqu’à présent, j’ai fait ce qui suit:

Guid activePowerScheme = GetActivePowerSchemeGuid(); IntPtr ptrActiveGuid = IntPtr.Zero; uint buffSize = 0; uint res = PowerReadACValue(IntPtr.Zero, ref activePowerScheme, ref ApplicationConstants.SLEEPGUID, ref ApplicationConstants.WAKETIMERGUID, IntPtr.Zero, IntPtr.Zero, ref buffSize); if (res == 0) { IntPtr ptrName = IntPtr.Zero; try { ptrName = Marshal.AllocHGlobal((int)buffSize); res = PowerReadACValue(IntPtr.Zero, ref activePowerScheme, ref ApplicationConstants.SLEEPGUID, ref ApplicationConstants.WAKETIMERGUID, IntPtr.Zero, ptrName, ref buffSize); byte[] ba = new byte[buffSize]; Marshal.Copy(ptrName, ba, 0, (int)buffSize); int retVal = BitConverter.ToInt32(ba, 0); if (retVal == 0) { return true; } else { return false; } } catch(Exception exp) { Logger.LogException(exp); return false; } finally { if (ptrName != IntPtr.Zero) { Marshal.FreeHGlobal(ptrName); } } } return false; 

Cela fonctionne la plupart du temps, mais lorsque je réinitialise mes parameters de plan d’alimentation, cela ne fonctionne pas bien (incohérent). J’ai aussi essayé ce qui suit:

 Guid currentPowerSchemeGuid = GetActivePowerSchemeGuid(); RegistryKey currentPowerSchemeKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes\" + currentPowerSchemeGuid.ToSsortingng()); if (currentPowerSchemeKey != null) { RegistryKey sleepRegKey = currentPowerSchemeKey.OpenSubKey(ApplicationConstants.SLEEPGUID.ToSsortingng()); currentPowerSchemeKey.Close(); if (sleepRegKey != null) { RegistryKey wakeTimerRegKey = sleepRegey.OpenSubKey(ApplicationConstants.WAKETIMERGUID.ToSsortingng()); sleepRegKey.Close(); if (wakeTimerRegKey != null) { wakeTimerRegKey.Close(); currentPowerSchemeKey.Close(); return true; } else { currentPowerSchemeKey.Close(); return false; } } else { currentPowerSchemeKey.Close(); return false; } } else { return false; } 

Cela ne fonctionne pas lors de la réinitialisation des parameters de plan d’alimentation, la clé de Registre GUID du minuteur de réveil est effacée. Existe-t-il un moyen approprié pour détecter si mon système prend en charge les timers?

Selon arx, essayé le code suivant et ça marche.

  public static bool IsWakeTimerSupported() { IntPtr timerHandle = CreateWaitableTimer(IntPtr.Zero, true, "Wait Timer 1"); uint retVal = GetLastError(); if (timerHandle != IntPtr.Zero) { CancelWaitableTimer(timerHandle); CloseHandle(timerHandle); timerHandle = IntPtr.Zero; } //SUCCESS if (retVal == 0) { return true; } else { return false; } } 

Le CancelWaitableTimer (timerHandle) peut être ignoré comme l’indique la documentation MSDN pour utiliser CloseHandle.

MODIFIER:

 public static bool IsWakeTimerSupported() { IntPtr timerHandle = CreateWaitableTimer(IntPtr.Zero, true, "Wait Timer 1"); long interval = 0; int retVal = 0; if (timerHandle != IntPtr.Zero) { SetWaitableTimer(timerHandle, ref interval, 0, IntPtr.Zero, IntPtr.Zero, true); retVal = Marshal.GetLastWin32Error(); WaitableTimer.CancelWaitableTimer(timerHandle); try { Win32.CloseHandle(timerHandle); } catch (Exception exp) { Logger.LogException(exp); } timerHandle = IntPtr.Zero; } //SUCCESS if (retVal == 0) { return true; } else { return false; } } 

Selon cet article, http://blogs.msdn.com/b/adam_nathan/archive/2003/04/25/56643.aspx, nous ne devrions jamais utiliser GetLastError via PInvoke.

Utiliser la bibliothèque powrprof.dll a fonctionné pour moi:

 using System; using System.ComponentModel; using System.Runtime.InteropServices; namespace Namespace { public static class PowerOptions { // src: https://msdn.microsoft.com/en-us/library/windows/desktop/hh448380%28v=vs.85%29.aspx private readonly static Guid HIGH_PERFORMANCE = new Guid("8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"); // aka MIN_POWER_SAVINGS private readonly static Guid BALANCED = new Guid("381b4222-f694-41f0-9685-ff5bb260df2e"); // aka TYPICAL_POWER_SAVINGS private readonly static Guid POWER_SAVER = new Guid("a1841308-3541-4fab-bc81-f71556f20b4a"); // aka MAX_POWER_SAVINGS private readonly static Guid ACDC_POWER_SOURCE = new Guid("5d3e9a59-e9D5-4b00-a6bd-ff34ff516548"); private readonly static Guid SLEEP_SUBCATEGORY = new Guid("238C9FA8-0AAD-41ED-83F4-97BE242C8F20"); private readonly static Guid WAKE_TIMERS = new Guid("bd3b718a-0680-4d9d-8ab2-e1d2b4ac806d"); public static Ssortingng GetCurrentPowerPlanFriendlyName() { IntPtr ptrActiveGuid = IntPtr.Zero; int ret = PowerGetActiveScheme(IntPtr.Zero, ref ptrActiveGuid); if (ret == 0) { uint buffSize = 0; ret = PowerReadFriendlyName(IntPtr.Zero, ptrActiveGuid, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref buffSize); if (ret == 0) { if (buffSize == 0) return ""; IntPtr ptrName = Marshal.AllocHGlobal((int) buffSize); ret = PowerReadFriendlyName(IntPtr.Zero, ptrActiveGuid, IntPtr.Zero, IntPtr.Zero, ptrName, ref buffSize); if (ret == 0) { Ssortingng name = Marshal.PtrToSsortingngUni(ptrName); Marshal.FreeHGlobal(ptrName); return name; } Marshal.FreeHGlobal(ptrName); } } throw new Win32Exception(ret, "GetCurrentPowerPlanFriendlyName"); } public static PowerStatus GetPowerStatus() { PowerStatus ps = new PowerStatus(); if (!GetSystemPowerStatus(ref ps)) throw new Win32Exception(Marshal.GetLastWin32Error(), "GetPowerStatus"); return ps; } public static bool GetWakeTimersEnabled(PowerSource powerSource = PowerSource.Current, PowerPlan powerPlan = PowerPlan.Current) { int ret = 0; if (powerSource == PowerSource.Current) { PowerStatus ps = GetPowerStatus(); if (ps.ACLineStatus == PowerLineStatus.Online) powerSource = PowerSource.PluggedIn; else powerSource = PowerSource.OnBattery; } if (ret == 0) { if (powerPlan == PowerPlan.Current) { IntPtr ptrPowerPlan = IntPtr.Zero; ret = PowerGetActiveScheme(IntPtr.Zero, ref ptrPowerPlan); if (ret == 0) { uint value = 0; if (powerSource == PowerSource.PluggedIn) ret = PowerReadACValueIndex(IntPtr.Zero, ptrPowerPlan, SLEEP_SUBCATEGORY, WAKE_TIMERS, ref value); else ret = PowerReadDCValueIndex(IntPtr.Zero, ptrPowerPlan, SLEEP_SUBCATEGORY, WAKE_TIMERS, ref value); if (ret == 0) { return (value == 1); } } } else { Guid guid = GetGuid(powerPlan); uint value = 0; if (powerSource == PowerSource.PluggedIn) ret = PowerReadACValueIndex(IntPtr.Zero, guid, SLEEP_SUBCATEGORY, WAKE_TIMERS, ref value); else ret = PowerReadDCValueIndex(IntPtr.Zero, guid, SLEEP_SUBCATEGORY, WAKE_TIMERS, ref value); if (ret == 0) { return (value == 1); } } } throw new Win32Exception(ret, "GetWakeTimersEnabled"); } public static Guid GetGuid(PowerPlan powerPlan) { if (powerPlan == PowerPlan.Balanced) return BALANCED; if (powerPlan == PowerPlan.HighPerformance) return HIGH_PERFORMANCE; if (powerPlan == PowerPlan.PowerSaver) return POWER_SAVER; throw new ArgumentException("Not a standard power plan: " + powerPlan); } [DllImport("powrprof.dll", SetLastError = true)] public static extern int PowerWriteACValueIndex(IntPtr RootPowerKey, Guid SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, uint AcValueIndex); [DllImport("powrprof.dll", SetLastError = true)] private static extern int PowerReadACValueIndex(IntPtr RootPowerKey, IntPtr SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, ref uint AcValueIndex); [DllImport("powrprof.dll", SetLastError = true)] private static extern int PowerReadACValueIndex(IntPtr RootPowerKey, Guid SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, ref uint AcValueIndex); [DllImport("powrprof.dll", SetLastError = true)] private static extern int PowerReadDCValueIndex(IntPtr RootPowerKey, IntPtr SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, ref uint AcValueIndex); [DllImport("powrprof.dll", SetLastError = true)] private static extern int PowerReadDCValueIndex(IntPtr RootPowerKey, Guid SchemeGuid, Guid SubGroupOfPowerSettingsGuid, Guid PowerSettingGuid, ref uint AcValueIndex); [DllImport("powrprof.dll", SetLastError = true)] private static extern int PowerGetActiveScheme(IntPtr UserRootPowerKey, ref IntPtr ActivePolicyGuid); [DllImport("powrprof.dll", SetLastError = true)] private static extern int PowerReadFriendlyName(IntPtr RootPowerKey, IntPtr SchemeGuid, IntPtr SubGroupOfPowerSettingsGuid, IntPtr PowerSettingGuid, IntPtr Buffer, ref uint BufferSize); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool GetSystemPowerStatus(ref PowerStatus lpSystemPowerStatus); } public enum PowerPlan { Current, HighPerformance, Balanced, PowerSaver, } public enum PowerSource { Current, OnBattery, PluggedIn } public struct PowerStatus { ///The AC power status. public PowerLineStatus ACLineStatus; ///The battery charge status. public PowerChargeStatus BatteryFlag; ///Returns a value between [0 to 100] or 255 if unknown. public byte BatteryLifePercent; ///Returns a value that indicates if the system is currently conserving power. public PowerSaveStatus SystemStatusFlag; ///Number of seconds of battery life remaining, or -1 if unknown. public int BatteryLifeTime; ///Number of seconds of batter life on a full charge, or -1 if unknown. public int BatteryFullLifeTime; } public enum PowerLineStatus : byte { Offline = 0, Online = 1, Unknown = 255, } [Flags] public enum PowerChargeStatus : byte { High = 1, Low = 2, Critical = 4, Charging = 8, NoBattery = 128, Unknown = 255, } public enum PowerSaveStatus : byte { Off = 0, On = 1, } }