Oneliner: shutdown at specified time

Ever wanted to reboot a Windows box at a specific time? How hard could it be? Unforunately way too hard.

The Restart-Computer cmdlet in Powershell unfortunately does not seem to have an option to schedule a for a later time or delay a restart. The old school “shutdown” command, does though. Unfortunately:

    /t xxx     Set the time-out period before shutdown to xxx seconds.
               The valid range is 0-315360000 (10 years), with a default of 30.
               If the timeout period is greater than 0, the /f parameter is
               implied.

The functionality is there but it’s a pain to use. I don’t want to have to do math to calculate the number of seconds until shutdown. That’s why we have computers after all!

PowerShell to the rescue after all! Consider the following example:

shutdown /r /t ([math]::ceiling((New-TimeSpan -End "2016-11-15 22:00").TotalSeconds)) /d p:1:1

This example will restart the server at 22:00 on 2016-11-15, with the reason of “Hardware: Maintenance (Planned)”.

Picking apart the command

As before, I like to take apart the command to show what makes it tick.

The command shutdown will call the “old school” shutdown command found at C:\Windows\System32\Shutdown.exe.

The /r parameter specifies that we want to do a reboot.

The /t parameter specifies that the next parameter is the number of seconds until restart.

The next parameter, ([math]::ceiling((New-TimeSpan -End "2016-11-15 22:00").TotalSeconds)) calculates the number of seconds until the desired shutdown time. We’ll take a deeper look at this further down.

The /d p:1:1 parameter specifies the shutdown code. For a full list of valid reason codes, run shutdown /?.

Picking apart that magic parameter

All the magic of calculating the number of seconds happens here:

([math]::ceiling((New-TimeSpan -End "2016-11-15 22:00").TotalSeconds))

In order to better understand this, let’s unpack the full command into a longer script.

# Generate a TimeSpan measuring the amount of time between now
# (the default when the "Start" parameter is omitted) and the
# end time (the desired shutdown time)
$timespan = New-TimeSpan -End "2016-11-15 22:00"

# Get the amount of time as seconds. We use TotalSeconds here
# and not Seconds, because Seconds only contains the seconds
# part of the time span. E.g. if the time span is 10 minutes
# 30 seconds, Seconds would be 30, and TotalSeconds would be
# 630.
$seconds = $timespan.TotalSeconds

# Unfornately, $seconds contains a lot of unneccessary decimals.
# Here, we're rounding it up to the nearest integer.
$seconds = [math]::ceiling($seconds)

# Finally, we're invoking the shutdown command with the desired
# parameters.
shutdown /r /t $seconds /d p:1:1

I hope this is clear. Happy rebooting!