-asJob and Wake-on-Lan packet across the network

by Brett.Osiewicz at 2013-03-31 07:21:48

After dumping my DHCP server, i would like to waken all of the workstations on my networks. My input would look something like this:

ComputerName,MACAddress
Computer1,00-1C-00-7E-05-BC
Computer2,00-1C-42-7E-05-BC
$env:COMPUTERNAME,00-1C-42-7E-05-CB

Each computer may take 1 minute or more in order to awaken from hibernation and answer a ping (my loop currently takes about 9 seconds a turn). Therefore, i would like to launch a separate background job for each workstation and then collect the results from each seperate job.

$results = Receive-Job -Name ResumedComputers

I can’t remember from where i got the Wake-on-Lan logic, but the "-asJob" portion comes from http://jdhitsolutions.com/blog/2011/11/ping-ip-range/

I have two problems

1. The loop doesn’t iterate.

2. How do I structure the function so that it runs as a seperate background job?



function Resume-Computer2
{
[CmdletBinding()]
[OutputType([String])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[Alias("comp")]
$ComputerName,

[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
$MACAddress,

[switch] $AsJob
)

#define a scriptblock we can run as a job if necessary
$sb = {
Param($MACAddress,$Computername)
for ($i = 1; $i -eq 3; $i++)
{
$mymac = $MACAddress.split('-') | ForEach-Object { [byte]('0x' + $_) }
$UDPclient = New-Object System.Net.Sockets.UdpClient
$UDPclient.Connect(([System.Net.IPAddress]::Broadcast),4000)
$Packet = [byte](,0xFF * 6)
$Packet += $mymac * 16
[void] $UDPclient.Send($packet, $packet.Length)
Write-verbose "Iteration $i"
#Break the loop if the target is already available
$Status = Test-Connection -Computername $Computername -Count 1 -Quiet -ErrorAction SilentlyContinue
If ($Status -eq $True) {Break}
}
$Result = New-Object -TypeName PSObject -Property @{"Status"=$Status; "Iteration"=$i; "Computername"=$Computername }
return $Result
} #end $sb


if ($AsJob) {
Start-Job -ScriptBlock $sb -Name ResumedComputers -ArgumentList $MACAddress, $Computername
} else
{
#run the command normally
Invoke-Command -ScriptBlock $sb -ArgumentList $MACAddress, $Computername
}
}
by DonJ at 2013-03-31 07:51:25
I’m not sure you do want to do that. Each background job is essentially a thread of PowerShell - that’s going to be a LOT of overhead on the computer running this, unless you build in some throttling.

That said, you simply build the function to accept a SINGLE computer name and to operate against that ONE computer. Then, call the function by using something like Start-Job { My-Function -ComputerName WORKSTATION }. The function shouldn’t contain a loop - it’s just going to hit one computer. You’d put that function in a larger script that enumerates your input file and runs the Start-Job call.
by Brett.Osiewicz at 2013-03-31 08:58:59
ok. Point taken about the overhead on the computer running this function. I have noticed a single instance of this function consuming more resources than I would have predicted, and I guess I made it more difficult than it needed to be.
by Brett.Osiewicz at 2013-03-31 09:07:56
Regarding my problem with the loop:

I had changed ($i = 1; $i -lt 3; $i++) to $i -eq 3 . That is why it wasn’t iterating. Now I know better.