2014-04-18 76 views
3

我需要以编程方式检测我的电脑(Windows 7/8)是否支持唤醒定时器。到目前为止,我已经做了以下内容:如何检测Windows系统是否支持唤醒定时器

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; 

这工作的大部分时间,但是当重置我的电源计划设置,这并不能很好地工作(不一致)。我还尝试了以下操作:

Guid currentPowerSchemeGuid = GetActivePowerSchemeGuid(); 

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

这对重置电源计划设置不起作用,唤醒计时器GUID注册表项将被清除。如果我的系统支持唤醒定时器,是否有适当的方法可以检测?

+2

试试看。换句话说,使用'CreateWaitableTimer'来创建一个定时器并调用'SetWaitableTimer'来激活定时器'fResume'设置为'TRUE'(并且超时设置为远处的某个点)。如果不支持唤醒定时器,该函数将成功,并且'GetLastError'将返回'ERROR_NOT_SUPPORTED'。用CancelWaitableTimer取消定时器。 – arx

+0

我在Windows 8平板电脑(只有Windows 8)上尝试了您的解决方案,并且SetWaitableTimer不返回ERROR_NOT_SUPPORTED。当我查看平板电脑上的电源选项时,唤醒计时器选项不可见。 –

回答

0

根据arx,尝试了下面的代码,它的工作原理。

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

如MSDN文档所述,使用CloseHandle可以忽略CancelWaitableTimer(timerHandle)。

编辑:

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

根据这篇文章,http://blogs.msdn.com/b/adam_nathan/archive/2003/04/25/56643.aspx我们绝不768,16通过的PInvoke使用GetLastError。

+0

即使当前'允许唤醒计时器'被禁用(电池和插入),在'Windows 8.1','retVal == 0'上。 – Loathing

0

使用powrprof.dll库工作对我来说:

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 String 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) { 
        String name = Marshal.PtrToStringUni(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 { 

    ///<summary>The AC power status.</summary> 
    public PowerLineStatus ACLineStatus; 

    ///<summary>The battery charge status.</summary> 
    public PowerChargeStatus BatteryFlag; 

    ///<summary>Returns a value between [0 to 100] or 255 if unknown.</summary> 
    public byte BatteryLifePercent; 

    ///<summary>Returns a value that indicates if the system is currently conserving power.</summary> 
    public PowerSaveStatus SystemStatusFlag; 

    ///<summary>Number of seconds of battery life remaining, or -1 if unknown.</summary> 
    public int BatteryLifeTime; 

    ///<summary>Number of seconds of batter life on a full charge, or -1 if unknown.</summary> 
    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, 
} 

} 
相关问题