Alisdair Craik

Alisdair Craik

N/A

Power saving with PowerShell – a script to hibernate PCs overnight and wake them in the morning

We were going to put an intro on this post quoting you some numbers about the cost of leaving desktop PCs on overnight ($26 to $100 per PC per year apparently), but seeing as this is an article about efficiency and the fact that you’re here probably means that you’ve already decided to save some money and some Co2, we’ll get right into it.

The following script can be used to hibernate computers at night when your users have gone home and then wake them in the morning ready for when your users arrive. To the users the computer is ready and waiting as if nothing had happened, but for your finance department and your environment guy things are looking a lot more rosey.

This script assumes three things:

  • That you can generate a list of PC names to hibernate (in this example we’re using Microsoft’s Get-ADComputer cmdlet and assume all PC names start with ‘PC’).
  • Your network is set up to allow Wake-On-LAN packets. Generally this means that your network switches will allow directed broadcasts.
  • You’ve got the Cmdlet Library installed on the PC or server you’re using to run the script.
### Usage: Sleep-Computers -SleepTime 22:00 -WakeTime 07:00 ###
 
Function Sleep-Computers
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory=$true)]$SleepTime,
        [Parameter(Mandatory=$true)]$WakeTime,
        [Parameter()][String[]]$Exclude
    )
 
    Process
    {
        ### Wait until it's time for the computers to hibernate ###
        ### We will use a try catch block here to abort if the time has been input incorrectly ###
 
        Try
        {
            Wait-Until $SleepTime
        }
        Catch [System.IO.InvalidDataException]
        {
            throw;
        }
 
        ### Get the computers to hibernate ###
 
        Write-Host "Gathering computer names..."
        $AllPCs = Get-ADComputer -Filter 'PC*' | select Name
 
        ### Take out the computers we are excluding ###
        ### Also exclude the computer running the script ###
 
        $Exclude += $Env:ComputerName
        $TargetPCs = $AllPCs | Where{$Exclude -notcontains $_}
 
        ### For each computer, get network adapter information ### 
        ### The MAC addresses from the network adapters are needed to wake the computers up in the morning ###
        ### Use ErrorAction SilentlyContinue because some of the computers may already be off ###
 
        Write-Host "Gathering MAC Addresses..."
        $NICs = Get-NetworkAdapter -ComputerName $TargetPCs -ErrorAction SilentlyContinue |Where{$_.MACAddress -ne $null} 
 
        ### Write the MAC addresses out to a file in case you want to wake computers outside of this script ###
 
        $NICs | Select-Object HostName, MACAddress | Export-Csv -Path ($Env:UserProfile + '\sleepingNICs.csv')
 
        ### Only suspend (hibernate) computers for which we have a MAC address stored ###
        ### Also select unique names so we only tell the computer to suspend once ###
 
        Write-Host "Suspending computers..."
        $NICs | Select-Object HostName -Unique | Suspend-Computer        
 
        ### Wait until wake up time ###
 
        Wait-Until $WakeTime
 
        ### Wake them up ###
 
        Write-Host "Waking computers..."
        $NICs | Start-Computer
    }
}

And that’s it.

Total savings from running the script for one year: $26 to $100 per PC.

Total cost for the one copy of the Cmdlet Library required to run the script: $29.

This script uses the Get-NetworkAdapter, Wait-Until, Start-Computer and Suspend-Computer cmdlets.

<< Back To The Blog