Remote, remote, remote! In the management of our machine fleet at the very first places of the must-haves we surely find the configuration of remote access no?
We have options such as RDP, SSH, and WinRM. However, we may encounter an issue if the machine is turned off.
You have a choice between calling someone on site to turn it on, going to the site yourself, doing everything yourself from your desk with WOL.
Which do you choose?
I would say that WOL is the clear winner.

What is Wake-on-LAN (WOL)?

Wake on LAN (WoL) is a standard belonging to the data-link layer that allows a computer to boot from a remote location, provided its MAC address is known.
The Ethernet packets that trigger the “wake up” are called Magic Packets.

The Magic Packet is basically a broadcast frame, consisting of a first synchronization part consisting of six bytes of FF hexadecimal value, followed by the MAC Address of the target node repeated 16 times, for a total of 96 bytes, and an optional password field that can be absent, 4 bytes long or 6 bytes (source Wikipedia ).
Okay the theory is fine, but tell me how to put it into practice….

How to send Wake-on-LAN (WOL) magic packet with PowerShell

The basic script is this along with explanatory comments:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#Define MAC target address,
# can contain the separators ":" or "-" or the hexadecimal string alone
$MAC = "1A:2B:3C:4D:5E:6F"
#convert MAC to byte array
$ByteArray = $MAC -replace "[:\-]" -split "(..)" -ne '' | ForEach-Object { [Byte] "0x$_"}
#Build Magic Packet according to WOL specs
[Byte[]] $MagicPacket = (,0xFF * 6) + ($ByteArray * 16)
#Use .NET method to build UdpClient object
$Client = New-Object System.Net.Sockets.UdpClient
#Set Magic Packet destination to broadcast address of our network on port 7
$Client.Connect(([System.Net.IPAddress]::Broadcast),7)
#Send Magic Packet
$Client.Send($MagicPacket,$MagicPacket.Length)
#Close UdpClient
$Client.Close()

This script obviously applies only to target machines present on our own network, so how do we do it if the target is on another network instead?

In this case we will have to rely on a “bridge” machine, a host that resides on the target network.

If needed, by enabling WinRM on the bridge machine, we can modify the script as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$MAC = "1A:2B:3C:4D:5E:6F"
$BRIDGE_HOST = "[HOST_DNS_NAME|HOST_IP]"
$script = {
	$ByteArray = $Using:MAC -replace "[:\-]" -split "(..)" -ne '' | ForEach-Object { [Byte] "0x$_"}
	[Byte[]] $MagicPacket = (,0xFF * 6) + ($ByteArray * 16)
	$Client = New-Object System.Net.Sockets.UdpClient
	$Client.Connect(([System.Net.IPAddress]::Broadcast),7)
	$Client.Send($MagicPacket,$MagicPacket.Length)
	$Client.Close()
}
Invoke-Command -ComputerName $BRIDGE_HOST -ScriptBlock $script -Credential (Get-Credential)

In this case, the script will be launched locally on our machine. In addition to the $MAC variable, we will also need to customize the $BRIDGE_HOST with the IP address or DNS name of the bridge machine. Invoke-Command will execute the $script code on the bridge machine after prompting us for login credentials with (Get-Credential).

wol powershell script

Conclusions

Although we can find several ready-made Wake-on-LAN programs on the Web, a native Windows solution allows us greater flexibility.
We will always be able to customize it according to our needs without particular difficulty, plus it allows us to integrate WOL into pre-existing workflows or simply add functionality to our favorite script collection. What do you think?