Powershell has a strong .NET Framework integration. Because of this, you can do some pretty cool things with it. As .NET provides an UDP-Cliet, we can use it to make a simple wake on lan script using powershell.
Calculating the broadcast address
In order to send the magic packet to wake the remote host, you’ll need the broadcast address of your network. If you do not already know it, you can calculate it using a local ip address (or network address) and the subnet mask.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function GetBroadcastAddress([string]$address, [string]$subnetMask) { # Convert the ip address strings into an array of bytes $addressBytes = $address -split "\." | ForEach { [byte] $_ }; $subnetMaskBytes = $subnetMask -split "\." | ForEach { [byte] $_ }; $broadcastBytes = New-Object byte[] 4; for($i = 0; $i -lt 4; ++$i) { # Invert the the bits of the subnet mask # We need to add 256 as the -bnot function yields a signed # integer/negative numbers $inverted = -bnot [byte] $subnetMaskBytes[$i] + 256; # link the address bytes with the inverted subnet mask $broadcastBytes[$i] = $addressBytes[$i] -bor $inverted; } return $broadcastBytes -join "."; } |
In order to use this function, simply pass in an address of your local network and the corresponding subnet mask.
1 2 |
$broadcast = GetBroadcastAddress "192.168.1.11" "255.255.255.0"; Write-Host "Broadcast: $broadcast"; |
Retrieving the mac address
If you do not know the mac address of the target computer, you can use arp to retrieve it. But this method requires, that you had at least one connection to the host (a ping should be enough).
1 2 3 4 5 6 7 8 9 |
function GetMacAddress([string]$address, [string]$delimiter = ":") { $arp = arp -a | findstr $address; if(!$arp) { return $null; } $arp = $arp.Trim() -split "\s+"; return $arp[1] -replace "-",$delimiter; } |
Now simply provide the target’s ip address to this function (and optionally a delimiter) and it will return the proper mac address, as long as an arp entry exists.
1 2 3 4 5 6 |
$mac = GetMacAddress "192.168.1.11"; if($mac) { Write-Host "MAC: $mac"; } else { Write-Host "host not found"; } |
Creating the magic packet
In order to wake up a pc we need to create the magic packet. The magic packet consists of 6 repetitions of the bytes 0xFF and 16 repetitions of complete mac address.
1 2 3 4 5 6 7 8 9 10 11 |
function CreateMagicPacket([string]$mac) { # Split the mac address at the character : and convert the parts to a byte # array using the 0x prefix, we make sure that the provided $_ value will be # interpreted as hex. [byte[]] $macBytes = $mac -split ":" | ForEach { [byte] "0x$_" }; # Now create an array of 6 repetitions of 0xFF and 16 repetitions # of the mac address [byte[]] $magicPacket = (,0xFF * 6) + ($macBytes * 16); return $magicPacket; } |
Now to create a magic packet, you simply call the above function with the desired mac address.
1 |
$magicPacket = CreateMagicPacket "AB:12:FF:AB:12:FF"; |
Sending the magic packet
Finally we have everything we need to wake the pc. In order to send the magic packet, we use .NET’s UdpClient.
1 2 3 4 5 6 |
function SendMagicPacket([byte[]]$magicPacket, [string]$broadcast, [uint32]$port) { $udpClient = New-Object System.Net.Sockets.UdpClient; $udpClient.Connect($broadcast, $port); $udpClient.Send($magicPacket, $magicPacket.Length); $udpClient.Close(); } |
Now you just need to provide the created magic packet, the broadcast address and the UDP Port to send the packet to. This is usually port 7 or 9.
1 2 |
$packet = CreateMagicPacket "AB:12:FF:AB:12:FF"; SendMagicPacket $packet "192.168.1.255" 9; |
Conclusion
Implementing a wake on lan script using powershell is quite easy. But you should not rely on the above method on retrieving the mac address of the host. As the arp cache could be purged, it’s recommended to store the mac address rather than trying to always retrieve it. And splitting the actual wake-up code into mutliple functions might be a bit over-the-top.
The attached example code contains, after the function definitions, a small snippet which makes use of all the functions above. It tries to wake up the host 192.168.1.11 with the subnet mask 255.255.255.0.