Powershell Workflow Parallel

powershell

I recently determined that I am able to run a workflow as parallel without using foreach. Syntax is below.

workflow Get-OS {
parallel {
    Get-WmiObject -Class Win32_OperatingSystem
    }
}

Is it possible to throttle this workflow without using "foreach"? If so, can I still use the pscomputer parameter when I call it? I know that this works…

workflow Get-OS {
param(
[string[]]$computers
)
foreach -parallel -throttlelimit 50 ($computer in $computers) {
    Get-WmiObject -ComputerName $computer -Class Win32_OperatingSystem
    }
}

I am not sure how to do this without creating a "$computers" parameter manually and calling it in the foreach. Doing it with the PSComputerName parameter would make reporting a LOT easier.

Best Answer

No - "Parallel" does not support a throttle limit


I think you are confusing two distinct functionalities in PowerShell Workflows:

  • Parallel (which is a Workflow Foundation keyword)
  • -Parallel (a Workflow-specific parameter to the foreach loop)

The Parallel keyword means: "Each of the following statements/sequences can be executed in parallel".

So a Parallel block in a workflow, like this:

Workflow Test-Parallel {
    Parallel{
        1
        2
        3
        4
    }
}

Is not guaranteed to return @(1,2,3,4) - it could return the numbers in any order.

To demonstrate this, try the following:

function Do-Stuff {
    param($i)

    Start-Sleep -Milliseconds $(Get-Random -Minimum 10 -Maximum 400)
    return $i
}

Workflow Test-Parallel {
    Parallel {
        Do-Stuff -i 1
        Do-Stuff -i 2
        Do-Stuff -i 3
        Do-Stuff -i 4
        Do-Stuff -i 5
        Do-Stuff -i 6
        Do-Stuff -i 7
        Do-Stuff -i 8
        Do-Stuff -i 9
        Do-Stuff -i 10
    }
}

Test-Parallel

You should see that the numbers 1 through 10 is returned in a somewhat shuffled order.


So, if you know all of the variables (ie. the computer names) beforehand, you could do:

Workflow Get-ParallelCS {
    Parallel {
        Get-WmiObject -PSComputerName "client01.domain.tld" -Class "Win32_ComputerSystem"
        Get-WmiObject -PSComputerName "client02.domain.tld" -Class "Win32_ComputerSystem"
        Get-WmiObject -PSComputerName "client03.domain.tld" -Class "Win32_ComputerSystem"
        Get-WmiObject -PSComputerName "client04.domain.tld" -Class "Win32_ComputerSystem"
        Get-WmiObject -PSComputerName "client05.domain.tld" -Class "Win32_ComputerSystem"
        Get-WmiObject -PSComputerName "client06.domain.tld" -Class "Win32_ComputerSystem"
        Get-WmiObject -PSComputerName "client07.domain.tld" -Class "Win32_ComputerSystem"
    }
}

Get-ParallelCS