Demo 1: Obtain Public IP of a Windows Machine

# Commands to run locally
$command1={(Invoke-WebRequest -URI ("ifconfig.me/ip")).Content}
$command2={(Get-ADComputer $env:computername).DistinguishedName -Replace "^CN=[^,]+,",''}
$job1=start-job -ScriptBlock $command1
$job2=start-job -ScriptBlock $command2
$resultJob1 = (get-job (get-job -id $job1.Id).ChildJobs.Id).Output
$resultJob2 = receive-job -id $job2.Id

Demo 2: run jobs on 1 remote machine

# Invoke-Command to toward a remote Windows machine
$remoteComputer="COLO-Panda"
function getPublicIp{
return (Invoke-WebRequest -URI ("ifconfig.me/ip")).Content;
}
$job2=invoke-command -computername $remoteComputer -scriptblock {
param($getPublicIp)
[ScriptBlock]::Create($getPublicIp).Invoke()
} -args ${Function:getPublicIp} -asjob
$resultJob2 = receive-job -id $job2.Id

Demo 3: run jobs on multiple computers sequentially

$remoteComputers="SHERVER006","SHERVER007"
$results=@()

function getPublicIp{
return (Invoke-WebRequest -URI ("ifconfig.me/ip")).Content;
}

function executeFunctionRemotely{
param(
$remoteComputer
)
#$credential=(get-credential)

do{
$session = New-PSSession -ComputerName $remoteComputer
write-host "Connecting to remote computer $remoteComputer..."
sleep -seconds 1
if ($session){write-host "Connected."}
} until ($session.state -match "Opened")

$job=invoke-command -session $session -scriptblock{
param($getPublicIp)
[ScriptBlock]::Create($getPublicIp).Invoke()
} -args ${Function:getPublicIp} -asjob
# Wait until job is completed
do{
$jobName=$job.Name
$jobState = (Wait-Job -Name $jobName).State
write-host "Checking status of $jobName..."
sleep -seconds 1
if ($jobState -eq "Completed"){write-host "$jobName completed."}
} until ($jobState -eq "Completed")

$result = receive-job $job.Id

# Cleanup Routine
Remove-Job -Name $job.Name -Force
#$job|Remove-Job
Remove-PSSession -id $session.Id

return $result;
}

foreach ($computer in $remoteComputers){
$result=executeFunctionRemotely -remoteComputer $computer
$results+=[PSCustomObject]@{ComputerName=$computer;PublicIp=$result};
}

$results

<#
Connecting to remote computer SHERVER006...
Connected.
Checking status of Job29...
Job29 completed.
Connecting to remote computer SHERVER007...
Connected.
Checking status of Job31...
Job31 completed.
PS C:\Windows\system32>
PS C:\Windows\system32> $results

ComputerName PublicIp
------------ --------
SHERVER006 9000.24.245.9000
SHERVER007 9000.24.245.9000
#>

Demo 3: run jobs on multiple computers simultaneously

$remoteComputers="SHERVER01","SHERVER02"
$results=@()
$jobs=@()

function pingDomain{
ping -n 100 google.com;
}

function startJobOnRemoteComputer{
param(
$remoteComputer,
$functionToCall
)

Write-Host "Executing $functionToCall on $remoteComputer";
$script=(Get-Item "function:$functionToCall").Definition

do{
$session = New-PSSession -ComputerName $remoteComputer
write-host "Connecting to remote computer $remoteComputer..."
sleep -seconds 1
if ($session){write-host "Connected."}
} until ($session.state -match "Opened")

$job=invoke-command -Session $session -AsJob -ScriptBlock{
param($functionToCall);
[ScriptBlock]::Create($functionToCall).Invoke();
} -args $script

write-host "$($job.Name) has been initiated on $remoteComputer"
return $job;
}

foreach ($computer in $remoteComputers){
$job=startJobOnRemoteComputer -remoteComputer $computer -functionToCall pingDomain
$jobs+=[PSCustomObject]$job;
}

$jobsCount=$jobs.count;
foreach ($job in $jobs){
# Wait until job is completed
do{
$jobName=$job.Name
$jobState = (Wait-Job -Name $jobName).State
write-host "Checking status of $jobName..."
sleep -seconds 1
if ($jobState -eq "Completed"){
write-host "$jobName completed.";
$result = receive-job $job.Id;
$results+=[PSCustomObject]@{ComputerName="$($job.Location)";Result="$result"};
Remove-Job -Name $job.Name -Force;
}
} until ($jobState -eq "Completed")
}

# Cleanup sessions
get-job|remove-job
get-pssession|remove-pssession

$output=$results|ft -autosize|out-string
write-host $output

<# Sample Result
PS C:\Windows\system32> write-host $output
ComputerName Result
------------ ------
SHERVER01 Pinging google.com [172.217.14.110] with 32 bytes of data: Reply from 172.217.14.110: bytes=32 tim...
SHERVER02 Pinging google.com [172.217.14.110] with 32 bytes of data: Reply from 172.217.14.110: bytes=32 time=..
#>