Search code examples
powershellwake-on-lan

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


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


Solution

  • 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#.