我需要以编程方式检测我的计算机(Windows 7/8)是否支持唤醒计时器。到目前为止,我已经执行了以下操作:
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注册表项被清除。有什么正确的方法可以检测我的系统是否支持唤醒计时器?
最佳答案
根据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我们不应该通过PInvoke使用GetLastError。