Powershell: Wake up on Lan 0.3

Nick asked, “This script looks good. Would you mind adding comments to it to describe its logic? Also, it doesn’t appear to like having colons in MAC addresses even though colons is pretty standard. Thanks for sharing your script!” (link).

Well Nick, here you are! I hope it helps!

param (
    [parameter(Position=0,
        Mandatory = $true,
        ParameterSetName="bymac",
        HelpMessage="Wake up a machine by known mac address.")]
    [string]
    $targetMac,
    [parameter(Position=0,
        mandatory = $true,
        ParameterSetName="byip",
        HelpMessage="Wake up a machine by last known IP address.")]
    [Net.IPAddress]
    $targetIP,
    [parameter(Position=1)]
    $network = [net.ipaddress]::Broadcast,
    [parameter(Position=2)]
    $subnet = [net.ipaddress]::Broadcast
)

try {
    #Convert -network and -subnet to Net.IPAddress objects if necessary.
    if($network.gettype().equals([string])) {
        $network = [net.ipaddress]::Parse($network);
    }
    if($subnet.gettype().equals([string])) {
        $subnet = [net.ipaddress]::Parse($subnet);
    }
    
    #find the broadcast address for the -network
    #eg. the broadcast address for the ip 192.168.1.101/255.255.255.0 is 192.168.1.255.
    $broadcast = new-object net.ipaddress (([system.net.ipaddress]::parse("255.255.255.255").address -bxor $subnet.address -bor $network.address))
    
    #attempt to figure out if the first value is an ip or mac address.
    #if we do this: wol.ps1 192.168.1.255
    #instead of this: wol.ps1 -targetIP 192.168.1.255
    try {
        $targetIP = [net.ipaddress]::Parse($targetMac.toupper()).tostring() # | Out-Null;
    } catch {
        #$_;
        try {
            [Net.NetworkInformation.PhysicalAddress]::Parse($targetMac.toupper().replace(".","").replace(":","").replace("-","")) | Out-Null;
        } catch {
            #$_;
        }
    }
    
    #Find our target mac address.
    #$targetIP isn't set in the above try..catch if it's a mac address.
    if($targetIP) {
        try {
            $nmac = (arp -a $targetIP | ? {$_ -imatch $targetIP}).split(" ") | ? {$_.trim().length -gt 0;} | %{ $_.trim(); };
            $targetMac = $nmac[1];
        }catch{
            throw "IP address is unknown.";
        }
    }
    
    $mac = [Net.NetworkInformation.PhysicalAddress]::Parse($targetMac.toupper().replace(".","").replace(":","").replace("-",""))
    
    <#"targetmac: " + $targetMac;
    "targetip: " + $targetip;
    "mac: " + $mac;#>
    
    #Setup 3 different endpoints for the common WOL ports.
    $u = New-Object net.sockets.udpclient
    $ep = New-Object net.ipendpoint $broadcast, 0
    $ep2 = New-Object net.ipendpoint $broadcast, 7
    $ep3 = New-Object net.ipendpoint $broadcast, 9
    
    #setup the payload.
    #6 bytes of 255 followed by the target mac 16 times.
    $payload = [byte[]]@(255,255,255,255,255,255);
    $payload += ($mac.GetAddressBytes()*16)
    
    #send it out a few times.
    for($i = 0; $i -lt 10; $i++) {
        $u.Send($payload, $payload.Length, $ep) | Out-Null
        $u.Send($payload, $payload.Length, $ep2) | Out-Null
        $u.Send($payload, $payload.Length, $ep3) | Out-Null
        "$(date) - WOL payload $($i+1)/10 sent to $targetMac on $broadcast/$subnet" | Write-Debug;
        sleep -Milliseconds 10;
    }
} catch {
    $_ | Write-Error;
}
#Win32_NetworkAdapter
#Win32_OperatingSystem
#Win32_NetworkClient
#Win32_SystemNetworkConnections