Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Schedule machine to wake up

What's the best way to programmatically cause a Windows XP (or above) machine to wake up at a specific time. (Ideally a lot like how Media Center can start up automatically to record a particular TV program)

I've got a Windows service (written in C#) and I'd like this service to be able to cause the machine it is hosted on to start up at predetermined times.

Are there any BIOS settings or prerequisites (eg. ACPI) that need to be configured for this to work correctly?

This machine would be using dialup or 3G wireless modem, so unfortunately it can't rely on Wake on LAN.

like image 228
David Gardiner Avatar asked Jul 17 '09 06:07

David Gardiner


People also ask

How do I schedule my computer to wake from sleep?

Here's how you can do that: Launch the Control Panel and head to Hardware and Sound > Power Options. Now, from there click on the Change plan settings for the current plan, select Change advanced power settings, expand the Sleep section, click on the Allow wake timers, and make sure it's set to Enable.

What is a wake timer?

A wake timer is a timed event that wakes the computer from a sleep or hibernate state at a specific time to perform scheduled tasks. Important wake timers includes things like a required reboot after a Windows update.

How do you set a wake up timer?

To do so, head to Control Panel > Hardware and Sound > Power Options. Click “Change plan settings” for the current power plan, click “Change advanced power settings,” expand the “Sleep” section, expand the “Allow wake timers” section, and ensure it's set to “Enable.”

How do I schedule a Wake on LAN?

To send the wake-up packet to one or more computers on your network, check them from the list, then click the Action button then Wake up. You can also schedule and automate the use of Wake On LAN: check the target computers from the list , then click the Action button then Schedule.


2 Answers

You can use waitable timers to wake from a suspend or hibernate state. From what I can find, it is not possible to programmatically wake from normal shut down mode (soft off/S5), in that case, you need to specify a WakeOnRTC alarm in BIOS. To use waitable timers from C#, you need pInvoke. The import declarations are:

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

You can use those functions in the following way:

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

You can then cancel the waitable timer with CancelWaitableTimer, using the returned handle as an argument.

Your program can hibernate and sleep using 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);
}

Your system may not allow programs to let the computer enter hibernation. You can call the following method to allow hibernation:

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();
}
like image 172
Boris Avatar answered Sep 21 '22 06:09

Boris


The task scheduler program in Win7, taskschd.msc (and I beleive XP as well) can be set to wake the system on different triggers. Those triggers can be schedule, time, event, etc.

In at least Win7, you need to set "Allow Wake Timers" to 'Enabled' for this to work. This setting is found under...

--> Control Panel\Hardware and Sound\Power Options
click - "Edit Plan Settings"
click - "Change advanced power setting"
expand - "Sleep"
Expand - "Allow Wake timers"

like image 28
etropic Avatar answered Sep 24 '22 06:09

etropic