WakeUp-Machines – A PowerShell script for Wake On LAN
These days, I give a lot of presentations and demos on Windows Server 2012. Of course, many involve Hyper-V related demos. Although I run most demos from PowerShell, since now I can, I modify a lot in my demo environment. And since I frequently use my environment I need to be able to prepare my start my environment, prepare it, run the demos, revert to the state it was in when I started and finally shut down my environment.
At least the start, preparation (including tests), reverting and shutting down are all done using PowerShell scripts. Sometimes I have only 15 minutes to connect my machines to power and network. In that time, I don’t have time to manually start everything and use a document to follow what needs to be done. And what about some basic tests to verify everything is working correctly?
Think about it: starting the machines, waiting until they are alive, connecting through RDP to some of them and some virtual machines, starting VMconnect sessions, starting Hyper-V Manager, Server Manager, PowerShell console, configuring networks, etc, etc. Quite easy to forget some steps and hit issues during demos.
I normally don’t connect my presentation machine to the external monitor (large screen, beamer, etc.) until the environment is ready. But to show the power of automation, I did show a technical audience once how I start my environment (up to the point when it is ready). People were obviously impressed with the amount of automation I used.
Last month I presented at a large Microsoft event and got some questions from colleagues as well on how I started my machines without touching them. The script used Wake On LAN, something most machines support these days and which is on most of them on by default. I simply connect my machines to my switch and turn them on from my presentation machine.
In this post, I share my script for others to use. The script follows some PowerShell best practices:
· The name of the script is in the Verb-Noun form.
· The script is documented with comment based help.
The only thing you need to get it to work is the Wake On LAN tool. Other than that, you should be able to use it right away, once you have created the CSV file with machine names.
So how does it work?
The script uses a CSV file with machines you want to wake up. It starts with the first and works its way down the list. Not only does it wake the machines, it also sends echo requests to verify IP connectivity. It continues to send requests (number configurable) and then goes on to the next machine with wake up. I have developed a progress bar which displays progress on the wake up, the echo request and remaining phase of sending/receiving echo requests/replies.
WakeUp-Machines
- #######################################################
- ##
- ## WakeUp-Machines.ps1, v1.0, 2012
- ##
- ## Created by Matthijs ten Seldam, Microsoft
- ##
- #######################################################
- <#
- .SYNOPSIS
- Starts a list of physical machines by using Wake On LAN.
- .DESCRIPTION
- WakeUp-Machines starts a list of servers using a Wake On LAN tool. It then sends echo requests to verify that the machine has TCP/IP connectivity. It waits for a specified amount of echo replies before starting the next machine in the list.
- .PARAMETER Machines
- The name of the file containing the machines to wake.
- .PARAMETER Interface
- The IP address of the interface to use to wake up the machines.
- .PARAMETER Subnet
- The subnet mask of the interface to use to wake up the machines.
- .EXAMPLE
- WakeUp-Machines machines.csv 192.168.0.1 255.255.255.0
- .EXAMPLE
- WakeUp-Machines c:\tools\machines.csv 192.168.0.1 255.255.255.0
- .INPUTS
- None
- .OUTPUTS
- None
- .NOTES
- Make sure the Wake On LAN command line tool is available in the same location as the script!
- The CSV file with machines must be outlined using Name, MAC Address and IP Address with the first line being Name,MacAddress,IpAddress.
- See below for an example of a properly formatted CSV file.
- Name,MacAddress,IpAddress
- Host1,A0DEF169BE02,192.168.0.11
- Host3,AC1708486CA2,192.168.0.12
- Host2,FDDEF15D5401,192.168.0.13
- .LINK
- https://blogs.technet.com/matthts
- #>
- param(
- [Parameter(Mandatory=$true, HelpMessage="Provide the path to the CSV file containing the machines to wake.")]
- [string] $Machines,
- [Parameter(Mandatory=$true, HelpMessage="Provide the IP address of the interface to use for Wake On LAN.")]
- [string] $Interface,
- [Parameter(Mandatory=$true, HelpMessage="Provide the subnet mask of the interface to use for Wake On LAN.")]
- [string] $Subnet
- )
- ## Predefined variables
- $WolCmd=".\wolcmd.exe"
- $TimeOut = 30
- $Replies = 10
- clear;Write-Host
- ## Verify if WOL tool exists
- try
- {
- Get-ChildItem $WolCmd | Out-Null
- }
- Catch
- {
- Write-Host "$WolCmd file not found!";Write-Host
- exit
- }
- ## Read CSV file with machine names
- try
- {
- $File=Import-Csv $Machines
- }
- Catch
- {
- Write-Host "$Machines file not found!";Write-Host
- exit
- }
- $i=1
- foreach($Machine in $File)
- {
- $Name=$Machine.Name
- $MAC=$Machine.MacAddress
- $IP=$Machine.IpAddress
- ## Send magic packet to wake machine
- Write-Progress -ID 1 -Activity "Waking up machine $Name" -PercentComplete ($i*100/$file.Count)
- Invoke-Expression "$WolCmd $MAC $Interface $Subnet" | Out-Null
- $j=1
- ## Go into loop until machine replies to echo
- $Ping = New-Object System.Net.NetworkInformation.Ping
- do
- {
- $Echo = $Ping.Send($IP)
- Write-Progress -ID 2 -ParentID 1 -Activity "Waiting for $Name to respond to echo" -PercentComplete ($j*100/$TimeOut)
- sleep 1
- if ($j -eq $TimeOut)
- {
- Write-Host "Time out expired, aborting.";Write-Host
- exit
- }
- $j++
- }
- while ($Echo.Status.ToString() -ne "Success" )
- ## Machine is alive, keep sending for $Replies amount
- for ($k = 1; $k -le $Replies; $k++)
- {
- Write-Progress -ID 2 -ParentID 1 -Activity "Waiting for $Name to respond to echo" -PercentComplete (100)
- Write-Progress -Id 3 -ParentId 2 -Activity "Receiving echo reply" -PercentComplete ($k*100/$Replies)
- sleep 1
- }
- $i++
- Write-Progress -Id 3 -Completed $true
- $Ping=$null
- }
You can download the script, tool and sample machine.csv here.
#######################################################
Update, June 3rd 2012
I have updated my script to be able to do without the wolcmd tool. As pointed out in the comments, it is possible to do this from within PowerShell. So I did some research in MSDN and rewrote my script.
The switches have changed as well. You can now provide the time out, repeat and number of magic packets to send. Run Get-Help .\WakeUp-Machines.ps1 to get additional help (-detailed, –examples, –full all supported).
WakeUp-Machines
- #######################################################
- ##
- ## WakeUp-Machines.ps1, v1.1, 2012
- ##
- ## Created by Matthijs ten Seldam, Microsoft
- ##
- #######################################################
- <#
- .SYNOPSIS
- Starts a list of physical machines by using Wake On LAN.
- .DESCRIPTION
- WakeUp-Machines starts a list of servers using Wake On LAN magic packets. It then sends echo requests to verify that the machine has TCP/IP connectivity. It waits for a specified amount of echo replies before starting the next machine in the list.
- .PARAMETER Machines
- The name of the file containing the machines to wake.
- .PARAMETER TimeOut
- The number of seconds to wait for an echo reply before continuing with the next machine.
- .PARAMETER Repeat
- The number of echo requests to send before continuing with the next machine.
- .EXAMPLE
- WakeUp-Machines machines.csv
- .EXAMPLE
- WakeUp-Machines c:\tools\machines.csv
- .INPUTS
- None
- .OUTPUTS
- None
- .NOTES
- Make sure the MAC addresses supplied don't contain "-" or ".".
- The CSV file with machines must be outlined using Name, MAC Address and IP Address with the first line being Name,MacAddress,IpAddress.
- See below for an example of a properly formatted CSV file.
- Name,MacAddress,IpAddress
- Host1,A0DEF169BE02,192.168.0.11
- Host3,AC1708486CA2,192.168.0.12
- Host2,FDDEF15D5401,192.168.0.13
- .LINK
- https://blogs.technet.com/matthts
- #>
- param(
- [Parameter(Mandatory=$true, HelpMessage="Path to the CSV file containing the machines to wake.")]
- [string] $Machines,
- [Parameter(Mandatory=$false, HelpMessage="Number of unsuccesful echo requests before continuing.")]
- [int] $TimeOut=30,
- [Parameter(Mandatory=$false, HelpMessage="Number of successful echo requests before continuing.")]
- [int] $Repeat=10,
- [Parameter(Mandatory=$false, HelpMessage="Number of magic packets to send to the broadcast address.")]
- [int] $Packets=2
- )
- Set-StrictMode -Version Latest
- clear;Write-Host
- ## Read CSV file with machine names
- try
- {
- $File=Import-Csv $Machines
- }
- Catch
- {
- Write-Host "$Machines file not found!";Write-Host
- exit
- }
- function Send-Packet([string]$MacAddress, [int]$Packets)
- {
- <#
- .SYNOPSIS
- Sends a number of magic packets using UDP broadcast.
- .DESCRIPTION
- Send-Packet sends a specified number of magic packets to a MAC address in order to wake up the machine.
- .PARAMETER MacAddress
- The MAC address of the machine to wake up.
- .PARAMETER
- The number of packets to send.
- #>
- try
- {
- $Broadcast = ([System.Net.IPAddress]::Broadcast)
- ## Create UDP client instance
- $UdpClient = New-Object Net.Sockets.UdpClient
- ## Create IP endpoints for each port
- $IPEndPoint1 = New-Object Net.IPEndPoint $Broadcast, 0
- $IPEndPoint2 = New-Object Net.IPEndPoint $Broadcast, 7
- $IPEndPoint3 = New-Object Net.IPEndPoint $Broadcast, 9
- ## Construct physical address instance for the MAC address of the machine (string to byte array)
- $MAC = [Net.NetworkInformation.PhysicalAddress]::Parse($MacAddress)
- ## Construct the Magic Packet frame
- $Frame = [byte[]]@(255,255,255, 255,255,255);
- $Frame += ($MAC.GetAddressBytes()*16)
- ## Broadcast UDP packets to the IP endpoints of the machine
- for($i = 0; $i -lt $Packets; $i++) {
- $UdpClient.Send($Frame, $Frame.Length, $IPEndPoint1) | Out-Null
- $UdpClient.Send($Frame, $Frame.Length, $IPEndPoint2) | Out-Null
- $UdpClient.Send($Frame, $Frame.Length, $IPEndPoint3) | Out-Null
- sleep 1;
- }
- }
- catch
- {
- $Error | Write-Error;
- }
- }
- $i=1
- foreach($Machine in $File)
- {
- $Name=$Machine.Name
- $MacAddress=$Machine.MacAddress
- $IPAddress=$Machine.IpAddress
- ## Send magic packet to wake machine
- Write-Progress -ID 1 -Activity "Waking up machine $Name" -PercentComplete ($i*100/$file.Count)
- Send-Packet $MacAddress $Packets
- $j=1
- ## Go into loop until machine replies to echo
- $Ping = New-Object System.Net.NetworkInformation.Ping
- do
- {
- $Echo = $Ping.Send($IPAddress)
- Write-Progress -ID 2 -ParentID 1 -Activity "Waiting for $Name to respond to echo" -PercentComplete ($j*100/$TimeOut)
- sleep 1
- if ($j -eq $TimeOut)
- {
- Write-Host "Time out expired, aborting.";Write-Host
- exit
- }
- $j++
- }
- while ($Echo.Status.ToString() -ne "Success" )
- ## Machine is alive, keep sending for $Replies amount
- for ($k = 1; $k -le $Repeat; $k++)
- {
- Write-Progress -ID 2 -ParentID 1 -Activity "Waiting for $Name to respond to echo" -PercentComplete (100)
- Write-Progress -Id 3 -ParentId 2 -Activity "Receiving echo reply" -PercentComplete ($k*100/$Repeat)
- sleep 1
- }
- $i++
- Write-Progress -Id 3 -Completed $true
- $Ping=$null
- }
Comments
Anonymous
January 01, 2003
I guess as a side note, this functionality is not available in Powershell version 2. I just installed the management framwork 4 and it worked. That being said, I am not sure about version 3.Anonymous
January 01, 2003
@Dan The Wake On LAN will work on both because it only sends a magic packet to specific MAC addresses. The script uses IP-addresses only to wait for a response and then continue. @Ryan I would need more info as to what you want to achieve. Windows supports autologon, you can logon through a remote PowerShell session or invoke remote PowerShell scripts. is that what you are looking for?Anonymous
January 01, 2003
great post, thanksAnonymous
January 01, 2003
great post, thanksAnonymous
January 01, 2003
The comment has been removedAnonymous
January 01, 2003
I have rewritten my script to send the magic packets from code. So an external tool is no longer needed.Anonymous
January 01, 2003
( 2 / 2 ) <# ---- For security reason, the code is fully commented ----
Verify if we support IPv6 or IPv4
if([System.Net.Sockets.Socket]::OSSupportsIPv6) { Write-Output "Your system supports IPv6" # Create a new communication channel using the UDP protocol $netUDPClient = New-Object System.Net.Sockets.UdpClient([System.Net.Sockets.AddressFamily]::InterNetworkV6) # Connect to the network using port 9 (this is the standard for WOL) on the multicast "All routers" address # To send to multicast address "All hosts", use address "FF02::1" instead $netUDPClient.Connect([System.Net.IPAddress]::Parse("FF02::2"), 9) } elseif([System.Net.Sockets.Socket]::OSSupportsIPv4) { Write-Output "Your system supports IPv4" # Create a new communication channel using the UDP protocol $netUDPClient = New-Object System.Net.Sockets.UdpClient([System.Net.Sockets.AddressFamily]::InterNetwork) # Connect to the network using port 9 (this is the standard for WOL) on the broadcast address $netUDPClient.Connect(([System.Net.IPAddress]::Broadcast),9) } else { Throw "ERROR: Neither IPv4, nor IPv6 are supported !" }
Send the magic packet to the network
[void]$netUDPClient.Send($szPacket, $szPacket.Length)
Release managed and unmanaged resources
[void]$netUDPClient.Dispose()
Remove used variables
Remove-Variable netUDPClient, szPacket, szMACAddress ---- For security reason, the code is fully commented ---- #> Cheers, Didier
Anonymous
June 02, 2012
But there's script which doesn't require exe tool, why not use that approach?Anonymous
September 25, 2012
Is there a solution where Wake On Lan will work, on PCs, which have dynamic ip addresses, rather than static ip addresses?Anonymous
September 25, 2012
Very nice, thanks for doing this with Windows resources instead of going to a separate binary.Anonymous
September 28, 2012
This is very useful to me as I manage a lab of computers. It's great this can be done without the wolcmd tool as well. Something that would take this a step further for me would be the ability to have each remote computer login to a local account from a PowerShell script. Is this possible? If so, how would I go about doing that?Anonymous
October 06, 2012
I've tried both incarnations of your script and both fail with an error message: . : Property 'Count' cannot be found on this object. Make sure that it exists. At C:tempWakeUp-Machines.ps1:137 char:93
- Write-Progress -ID 1 -Activity "Waking up machine $Name" -PercentComplete ($i*100/$file. <<<< Count) + CategoryInfo : InvalidOperation: (.:OperatorToken) [], RuntimeException + FullyQualifiedErrorId : PropertyNotFoundStrict In spite of the error the script does wake up a machine. What am I missing?
Anonymous
October 08, 2012
Matthijs, Please allow me to more specific about what I want. I want the machines to login to the desktop so that the computer becomes available to lab users that aren't given any login credentials. I don't want to use auto login because I want to be able to control when the machines become available to the lab users. Thanks for your help.Anonymous
October 08, 2012
The comment has been removedAnonymous
October 08, 2012
Dan, I too have a dynamic IP envirnment. I looked up System.Net.NetworkInformation.Ping.Send(string) and it looks like it will take either a host name or an IP address. I plan on giving it a host name. You may want to do the same. Then there is no longer any reason to have an IP address column in the CSV.Anonymous
October 08, 2012
Ryan, That fix resolved my issue. Thanks!Anonymous
October 09, 2012
Guys, the IP address is not necessary at all for waking the machines. I use it to verify whether the specific machine has its IP-stack loaded, so basically if the wake up has succeeded. Indeed, if you only want to wake machines and are not interested in the result, you can do without.Anonymous
March 26, 2013
Hello, I am totally new to all this scripting business. I would like to automate this script, ie run it without any input from me. So far, I have found a batch script that will run it without having to input the csv filename but I can't get it to automate so that I don't need to type in text to send as the wake up call. How can I do this? regards, CarolineAnonymous
March 29, 2013
Trying to find a way to WOL via a specific port. We have an issue at some of our locations with the default port. Want to use one we know is open.Anonymous
July 31, 2013
msdn.microsoft.com/.../system.net.networkinformation.physicaladdress.parse.aspx
Construct physical address instance for the MAC address of the machine (string to byte array)
$MAC =[Net.NetworkInformation.PhysicalAddress]::Parse(($MacAddress -replace ':','-').ToUpper() )
Anonymous
November 25, 2013
Instead of using a csv file to load all the mahine names manually, can you just use MAC FF:FF:FF:FF:FF:FF and the broadcast ip 192.168.1.255 and wake up all the computers on the whole network at the same time? The broadcast MAC is referenced on this page: en.wikipedia.org/.../Broadcast_trafficAnonymous
February 19, 2014
For some reason, I can't get the script to work.. It's reading my MAC address right (I did a Write-Host) but the machine won't wake up. I've used a wake on LAN utility to wake this machine before... but I can't get this script to do it. What could I be doing wrong? It's not spitting out any errors. Below is my csv file contents... Name,MacAddress,IpAddress Cloud3,001E4FB9CB14,192.168.168.138 Cloud1,0026B98026F8,192.168.168.198Anonymous
March 03, 2014
Does this PS script work on Powershell 1.0 or is there a minimum version?Anonymous
March 03, 2014
Great script - I am looking to schedule the script to do a morning 'wake' of all site machines which I've managed to achieve. Would you mind sharing how you might go about adding in success and error logs?
Thanks,
GaryAnonymous
May 29, 2014
Caroline,
Using the wolcmd.exe utility, here is a section of the script that includes changes that I had to make to make this fully automated. Just replace the part that starts with ##Predefined variables.
## Predefined variables
$WolCmd="C:Scriptswolcmd.exe"
$TimeOut = 30
$Replies = 10
[tag:These] replace the parameters specified in the original script
#[tag:Location] of your .csv file
$Machines = "C:Scriptswol_chicago.csv"
#[tag:Interface] of the system from where your WoL packet is being sent
$Interface = "192.168.0.1"
#[tag:Subnet] mask of destination PC that you are trying to wake up
$Subnet = "255.255.255.224"
clear;Write-Host
## Verify if WOL tool exists
try
{
Get-ChildItem $WolCmd | Out-Null
}
Catch
{
Write-Host "$WolCmd file not found!";Write-Host
exit
}
## Read CSV file with machine names
try
{
$File=Import-Csv $Machines
}
Catch
{
Write-Host "$Machines file not found!";Write-Host
exit
}
$i=1
foreach($Machine in $File)
{
$Name=$Machine.Name
$MAC=$Machine.MacAddress
$IP=$Machine.IpAddress
## Send magic packet to wake machine (Made changes here next to Invoke-Expression)
Write-Progress -ID 1 -Activity "Waking up machine $Name" -PercentComplete ($i100/$file.Count)
Invoke-Expression "$WolCmd $MAC $IP $Subnet" | Out-Null
$j=1
## Go into loop until machine replies to echo
$Ping = New-Object System.Net.NetworkInformation.Ping
do
{
$Echo = $Ping.Send($IP)
Write-Progress -ID 2 -ParentID 1 -Activity "Waiting for $Name to respond to echo" -PercentComplete ($j100/$TimeOut)
sleep 1
if ($j -eq $TimeOut)
{
Write-Host "Time out expired, aborting.";Write-Host
exit
}
$j++
}
while ($Echo.Status.ToString() -ne "Success" )
## Machine is alive, keep sending for $Replies amount
for ($k = 1; $k -le $Replies; $k++)
{
Write-Progress -ID 2 -ParentID 1 -Activity "Waiting for $Name to respond to echo" -PercentComplete (100)
Write-Progress -Id 3 -ParentId 2 -Activity "Receiving echo reply" -PercentComplete ($k*100/$Replies)
sleep 1
}
$i++
Write-Progress -Id 3 -Completed $true
$Ping=$null
}Anonymous
August 29, 2014
For some reason the standard 255.255.255.255 broadcast address was not working on my set-up, but would work if I sent the magic packet to just the broadcast address for my local subnet at 192.168.1.255.
To get this to work in your second v1.1 script I changed:
$Broadcast = ([System.Net.IPAddress]::Broadcast)
to read:
$Broadcast = ([System.Net.IPAddress]::Parse("192.168.1.255"))Anonymous
September 15, 2014
The comment has been removedAnonymous
September 24, 2014
Notice that as this script goes through the CSV list, if it comes across a machine that it does not get a response from (because the machine is powered off or the user has their laptop out of the office), it times out and exits the scipt. How do you get the script to continue to read from the CSV even if a machine does not respond? Can't for the life of me figure it out.Anonymous
November 04, 2014
I have the same issue as Troy T that the script exit when a computer is not reachable over the network..hope that someone has a solution for thatAnonymous
December 21, 2014
There’s a small Windows CMD script that I use to WOL PCs:
http://www.sysadmit.com/2014/05/pequeno-script-para-despertar-equipos-con-wake-on-lan.htmlAnonymous
December 22, 2014
I'm new to powershell. I used to have a similar VBS script but can't for the life of me find the darn thing. Anyway, sorry to flog a two year old post but maybe someone can still hlep.
When I try to run the cmdlet I get "The term 'wakeup-machines' is not recognized as the name of a cmdlet"
I'm running a powershell window in the directory where the cmdlet resides... Any thoughts?Anonymous
February 10, 2015
Hi Matthijs
Great script I must say how can I actually get the script to start all the machines on the CSV file without putting in the parameters when I run the script.Anonymous
June 19, 2015
Great script but I have the same issue as Flemming and troy is there a solutionAnonymous
September 29, 2015
Matthijs ... I hope you don't mind, I used your script and modified it a little. I modified the script to import the DHCPServer module for PS. It then gets a collection of lease objects from the DHCP server, and uses that data to iterate over every machine using "Send-Packet". I also changed it slightly to send all Wake On LAN packets, and then go back and ping test all of them.
Here is the final/current version
http://hastebin.com/odoqefawew.parser3