How to send a Wake-on-LAN magic packet using PowerShell?
Asked Answered
C

2

9

I want to send a WOL magic packet using PowerShell, without falling back on any third party tools.

Cheder answered 4/7, 2022 at 8:4 Comment(0)
C
14

Here is the working PowerShell one-liner I am using to send a WakeOnLan packet:

'01-23-45-67-89-AB' | Set-Variable 'mac'; [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | Where-Object { $_.NetworkInterfaceType -ne [System.Net.NetworkInformation.NetworkInterfaceType]::Loopback -and $_.OperationalStatus -eq [System.Net.NetworkInformation.OperationalStatus]::Up } | ForEach-Object { $targetPhysicalAddressBytes = [System.Net.NetworkInformation.PhysicalAddress]::Parse(($mac.ToUpper() -replace '[^0-9A-F]','')).GetAddressBytes(); $packet = [byte[]](,0xFF * 102); 6..101 | Foreach-Object { $packet[$_] = $targetPhysicalAddressBytes[($_ % 6)] }; $client = [System.Net.Sockets.UdpClient]::new([System.Net.IPEndPoint]::new(($_.GetIPProperties().UnicastAddresses | Where-Object { $_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork })[0].Address, 0)); try { $client.Send($packet, $packet.Length,[System.Net.IPEndPoint]::new([System.Net.IPAddress]::Broadcast, 9)) | Out-Null } finally { $client.Dispose() } }

And here is a more readable version:

$mac = '01-23-45-67-89-AB';
[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() | Where-Object { $_.NetworkInterfaceType -ne [System.Net.NetworkInformation.NetworkInterfaceType]::Loopback -and $_.OperationalStatus -eq [System.Net.NetworkInformation.OperationalStatus]::Up } | ForEach-Object {
    $networkInterface = $_
    $localIpAddress = ($networkInterface.GetIPProperties().UnicastAddresses | Where-Object { $_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork })[0].Address
    $targetPhysicalAddress = [System.Net.NetworkInformation.PhysicalAddress]::Parse(($mac.ToUpper() -replace '[^0-9A-F]',''))
    $targetPhysicalAddressBytes = $targetPhysicalAddress.GetAddressBytes()
    $packet = [byte[]](,0xFF * 102)
    6..101 | Foreach-Object { $packet[$_] = $targetPhysicalAddressBytes[($_ % 6)] }
    $localEndpoint = [System.Net.IPEndPoint]::new($localIpAddress, 0)
    $targetEndpoint = [System.Net.IPEndPoint]::new([System.Net.IPAddress]::Broadcast, 9)
    $client = [System.Net.Sockets.UdpClient]::new($localEndpoint)
    try { $client.Send($packet, $packet.Length, $targetEndpoint) | Out-Null } finally { $client.Dispose() }
}

All common MAC address formats are supported and casing doesn't matter, for example:

  • 0123456789aB
  • 01-23-45-67-89-aB
  • 01:23:45:67:89:aB
  • 0123.4567.89aB

Works in powershell.exe (.NET Framework) and pwsh.exe (.NET/.Net Core).

Loosely based on code from Wake on LAN using C#.

Cheder answered 4/7, 2022 at 8:4 Comment(10)
You probably want to give the MAC without ':' signs.Venation
@BartoszRosa There are multiple formats supported (including macs without : separators). See PhysicalAddress.Parse Method for more information.Cheder
Yes, but in my case, PowerShell Parse() method raises an exception with this format. In any case, thanks for the code.Venation
@BartoszRosa Yes, if you are using an older PowerShell version (like one that ships with Windows instead of pwsh), it will not support this format (see PhysicalAddress.Parse Method). I'll can change the MAC format in the sample code to something that works in all versions.Cheder
Note you'd have to be on the same network, fast startup would have to be disabled in windows 10, probably on dells wake on lan would have to be enabled, and deep sleep disabled.Numismatist
I updated the answer so that all common Mac address formats work with both: powershell.exe and pwsh.exe.Cheder
The dell bios utility "cctk" doesn't work with all dell models either.Numismatist
cctk fix: remove these devices and reboot: 'Microsoft System Management BIOS Driver', 'Microsoft Windows Management Interface for ACPI'Numismatist
It's nice to keep a hastable of computernames and macaddresses.Numismatist
Its pretty simple to funnel multiple MAC addresses through this script. For example: '0123456789aB', '123456789aBc' | ForEach-Object { $_ | Set-Variable 'mac' <# ... #> }Cheder
N
0

I use this one. I turned the function into a script: Wake On LAN - powershell.one https://powershell.one/code/11.html

I make a macaddress computername hashtable like this with an infoblox hostaddress csv:

import-csv ~\allmacs.csv |
% { $mac = @{} } {
  $mac[$_.'parent*' -replace '.stackoverflow.com' -replace
   '.stackoverflow.com2'] = $_.mac_address }

$mac['a001']
6c:3c:9c:39:46:74

icm a001 invoke-wakeonlan.ps1 -args (,$mac[(echo a002 a003)])
Numismatist answered 25/4 at 16:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.