Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
PSRemoting jobs are quite amazing. While they are a little complicated to grasp at first, they’re quite powerful. However, with great power usually comes great responsibility. We know we can spawn a gazillion jobs, but how about managing them? How many do we have to do? What did they return, etc.
Here’s a skeleton function that does nothing more than return two [Datetime] objects separated by 10 seconds.
function Get-PsRemotingJobsExample
{
param (
[Parameter(ValueFromPipeLine=$true)][String[]]$ComputerName = @($env:ComputerName),
[int]$TimeoutInterval = 60,
[int]$JobPollingInterval = 5,
[int]$ThrottleLimit = 100,
[switch]$ShowRunspaceID
)
begin
{
$scriptBlock = {
Get-Date; Start-Sleep -Seconds 10; Get-Date;
} # $scriptblock
$jobs = New-Object System.Collections.ArrayList;
} # begin
process
{
foreach ($computer in $ComputerName)
{
if (($Computer -match "^$env:ComputerName\.") -or ($Computer -match "^$env:ComputerName$"))
{
$jobs.Add((Start-Job -ScriptBlock $scriptblock -ArgumentList $arguments)) | Out-Null;
} # if (($Computer -match "^$env:ComputerName\.") -or ($Computer -match "^$env:ComputerName$"))
else
{
$jobs.Add((Invoke-Command -AsJob -ScriptBlock $scriptblock -ArgumentList $arguments -ComputerName $computer -ThrottleLimit $ThrottleLimit )) | Out-Null;
} # if (($Computer -match "^$env:ComputerName\.") -or ($Computer -match "^$env:ComputerName$")) ... else
} # foreach ($computer in $ComputerName)
} # process
end
{
$initialCount = $jobs.Count;
$notAfter = (Get-Date) + (New-TimeSpan -Seconds $TimeoutInterval);
while ($jobs)
{
$now = Get-Date;
if ($now -gt $notAfter) { break; }
Write-Progress $now "$($jobs.Count)/$initialCount jobs and $([int]($notAfter - $now).TotalSeconds) seconds to go.";
Get-Job -Id ($jobs | % { $_.Id }) |
? { $_.State -ne 'Running' } |
% {
if ($_.State -eq 'Completed')
{
if ($data = (Receive-Job -Id $_.Id))
{
if ($ShowRunspaceID)
{
$data;
} # if ($ShowRunspaceID)
else
{
$properties = $data | Get-Member -MemberType *Propert* |
% {
if ($_.name -ne 'RunspaceId')
{
$_.name;
} # if ($_.name -ne 'RunspaceId')
} # $properties = $data | Get-Member -MemberType *Propert* |
$data | Select-Object -Property $properties;
} # if ($ShowRunspaceID) ... else
} # if ($data = (Receive-Job -Id $_.Id))
else
{
Write-Warning "No data-received from job at $($_.Location)";
} # if ($data = (Receive-Job -Id $_.Id)) ... else
Remove-Job -id $_.Id;
} # if ($_.State -eq 'Completed')
else
{
Write-Warning "JobId $($_.Id) failed. Please investigate.";
} # if ($_.State -eq 'Completed') ... else
$jobs.Remove($_) | Out-Null;
} # Get-Job -Id ($jobs | % { $_.Id }) | ? { $_.State -ne 'Running' }
if ($jobs) { start-sleep $JobPollingInterval; }
} # while ($jobs)
} # end
} # function Get-PsRemotingJobsExample
Comments
- Anonymous
May 20, 2014
Updated to mask out RunspaceID property by default, and to add -ThrottleLimit = 100