安排机器唤醒

Dav*_*ner 15 c# windows-services acpi

以编程方式使Windows XP(或更高版本)计算机在特定时间唤醒的最佳方法是什么.(理想情况下,Media Center可以自动启动录制特定电视节目)

我有一个Windows服务(用C#编写),我希望这项服务能够使托管的机器在预定的时间启动.

是否有任何BIOS设置或先决条件(例如ACPI)需要配置才能正常工作?

这台机器将使用拨号或3G无线调制解调器,所以不幸的是它不能依赖局域网唤醒.

Bor*_*ris 12

您可以使用等待计时器从挂起或休眠状态唤醒.根据我的发现,无法以编程方式从正常关闭模式唤醒(软关闭/ S5),在这种情况下,您需要在BIOS中指定WakeOnRTC警报.要使用C#中的等待计时器,您需要pInvoke.进口申报是:

public delegate void TimerCompleteDelegate();

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetWaitableTimer(IntPtr hTimer, [In] ref long pDueTime, int lPeriod, TimerCompleteDelegate pfnCompletionRoutine, IntPtr pArgToCompletionRoutine, bool fResume);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CancelWaitableTimer(IntPtr hTimer);
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式使用这些功能:

public static IntPtr SetWakeAt(DateTime dt)
{
    TimerCompleteDelegate timerComplete = null;

    // read the manual for SetWaitableTimer to understand how this number is interpreted.
    long interval = dt.ToFileTimeUtc(); 
    IntPtr handle = CreateWaitableTimer(IntPtr.Zero, true, "WaitableTimer");
    SetWaitableTimer(handle, ref interval, 0, timerComplete, IntPtr.Zero, true);
    return handle;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以CancelWaitableTimer使用返回的句柄作为参数取消等待计时器.

您的程序可以使用pInvoke休眠和休眠:

[DllImport("powrprof.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);

public static bool Hibernate()
{
    return SetSuspendState(true, false, false);
}

public static bool Sleep()
{
    return SetSuspendState(false, false, false);
}
Run Code Online (Sandbox Code Playgroud)

您的系统可能不允许程序让计算机进入休眠状态.您可以调用以下方法以允许休眠:

public static bool EnableHibernate()
{
    Process p = new Process();
    p.StartInfo.FileName = "powercfg.exe";
    p.StartInfo.CreateNoWindow = true;
    p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    p.StartInfo.Arguments = "/hibernate on"; // this might be different in other locales
    return p.Start();
}
Run Code Online (Sandbox Code Playgroud)