Invoke-Parallel - Parallel PowerShell

This function will take in a script or scriptblock, and run it against specified objects(s) in parallel. It uses runspaces, as there are many situations where jobs or PSRemoting are not appropriate.

4 Star
9,389 times
Add to favorites
E-mail Twitter Digg Facebook
Sign in to ask a question

  • Get-RunspaceData : The term 'New-AzureRmDisk' is not recognized
    1 Posts | Last post November 09, 2018
    • In Invoke-Parallel i am creating a new disk with a command New-AzureRmDisk, then it gives an error: Get-RunspaceData : The term 'New-AzureRmDisk' is not recognized as the name of a cmdlet, function, or script file.......
      $servers = 1..2
      Invoke-Parallel -InputObject $servers -ScriptBlock {
      New-AzureRmDisk -Disk .................
      Please suggest me the solution for the same.
      Thanks and Regards
  • How we can use Invoke-Parallel to fetch ADUser data ?
    1 Posts | Last post October 04, 2018
    • How we can use Invoke-Parallel to fetch ADUser data?
      I want to get all the users from AD and foreach user I want to fetch multiple properties parallel. 
      Becasue ForEach process is taking time to get the details. 
      sample dummy code. 
      $users = Get-ADUser -Filter *
      ForEach($user in $users){
      $SamName = $user.samaccountname
       $memberof = $user.memberof
      <More properties like above>
  • How to use in Azure runbook?
    2 Posts | Last post August 31, 2018
    • I want to use this fix an issue I have with an Azure runbook I currently use for starting up to 50VMs each morning. How can I implement this as part of a runbook, can I import this somehow?
    • You can import the module going to the "Modules Gallery" menu, and importing the module WFTools that adds several cmdlet's including InvokeParallel . This was published by the same user.
      I use it this way:
      $VMs = Get-AzureRmVM -ResourceGroupName $RG
      $VMs | Invoke-Parallel -ImportVariables -NoCloseOnTimeOut -ScriptBlock {
          Start-AzureRMVM -ResourceGroup $_.ResourceGroupName -Name $_.Name -Verbose
  • Add jobs on the fly
    1 Posts | Last post July 26, 2017
    • I am building a script that will receive new input during execution (for example it may monitor a folder for new files) and perform some long process on each item.  I want to use Invoke-Parallel or something similar, however I'm not sure how, or if, I can add items to the queue when it's already started.
      Lets say, for example, I have a folder with 100 .csv files in it, and I kick off invoke-parallel to process those 100 (5 at a time)... while it's running, 20 more files are added, is there any way to add those new 20 to the queue?
  • Running it against AD Objects in a large environement
    2 Posts | Last post December 14, 2016
    • I thinking about using invoke-Parallel to run scripts against AD. to sum it up, I doing a lot security filtering rights management in bulk. I'd hate to be the who brought the house down. Do you think it would be safe doing so?
    • Presumably, although you might want to somehow gate to a particular domain controller to avoid potential issues with replication.
      How would you go about this?  You might also consider something less heavy-weight like ADSI, if that's possible, vs. having to load the AD module or Quest snapin, which can ding performance a bit.
  • Access Completed Count
    1 Posts | Last post September 20, 2016
    • Is there a way to access any of the count variables that are inside invoke-parallel? I want to rename files and append each with the iteration of the completed count. Cant seem to get it work by normal means so I thought maybe I could use what is already built in. Also tried to access a count variable using $parameter but no dice.
  • Get-Runspace Data error - Teamcity
    2 Posts | Last post August 25, 2016
    • Hi,
      I am struggling to get this script working correctly. Hoping you could provide some advice.
      I wrote a script that deletes an azure vm then recreates it from a baseline VHD. I am invoking that script in parallel like so.
      [array]$VmInfo= @{vmName = "server1"; baseVHD = "Cool.vhd" }
      $VmInfo +=  @{vmName = "server2"; baseVHD = "Cooler.vhd" }
      $VmInfo | Invoke-Parallel -Quiet -ScriptBlock { c:\myscript.ps1 -vmName $_.vmName -baseVHD $_.baseVHD}
      This works whenever I run it from my machine but when I run it from a teamcity build step I get errors like this. It appears to run only one of the threads and not both.
      Get-RunspaceData : Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: indexAt 
      C:\BuildAgent\work\92c00c526b378335\Modules\common.psm1:1407 char:13
      Get-RunspaceData -wait
      CategoryInfo          : NotSpecified: (:) [Write-Error], ArgumentOutOfRangeExceptionFullyQualifiedErrorId : System.ArgumentOutOfRangeException,Get-RunspaceData
      *Note I put the invoke-parallel in as a module that gets loaded before executing.
      Am I doing this correctly? Any Idea whats going on?
    • Hi bigminer!
      Would you mind opening an issue on GitHub (
      It might be handy to see a sanitized version of your myscript.ps1 file - you can use code highlighting on github like so:
      Some-Arbitrary -PowerShell
      Will-Show -Up Highlighted
  • Shutdown Start of All VMs together
    2 Posts | Last post June 29, 2016
    • HI,
      I am trying to use this script for shutting down all VMs simultaneously. There is one way of it i.e. Workflow. Since, Nano Server is not supporting Workflow execution, so I am stuck. I tried to pass a txt file as a Input object, which contains the name of the VMs, but it's not working. Any help on this highly appreciable.
    • I got the solution. I ran the workflow by using -PSComputerName from Remote server to Nano Server.
  • My $results variable is empty after parallel run ends..
    3 Posts | Last post April 19, 2016
    • $results = $urls | Invoke-Parallel -ImportModules -ImportVariables -throttle $maxConcurrentJobs -ScriptBlock {
              #Run Web-Request & catch the error details, if exception raised
              try {
                  $pagecontent = Invoke-WebRequest -Uri $_
              catch [System.Net.WebException] {
                  $errorcode = $_.Exception.Response.StatusCode.Value__
                  #$_ | fl * -Force
                  $webExepCol += $_,"The remote server returned an error: $errorcode"
                  Write-Error -Message "The remote server returned an error for uri: $_`n, Error code: $errorcode`n" -Category ConnectionError
                  $Host.UI.WriteErrorLine("The remote server returned an error for uri: $_`n, Error code: $errorcode`n")
              $innerHTML = $pagecontent.links.innerHTML
              #Get a list of Share host uris ONLY and add them to a global output list
              $ulLinks = ([regex]::matches($innerHTML, $using:matchstr) | %{$_.value})
              Write-Verbose "Extracted the following links: $ulLinks`n"
              #Add resulting links from extracted URI to output collection.
              $outCol += $ulLinks
      How do I get the final resulting collection (which is declared outside the script, and i import it using the '-ImportVariables' switch)? Because it returns empty.
    • Found a solution - simply added a return statement at the end of the scriptblock:
      return $ulLinks
    • Hi!
      So! ImportVariables will import variables, but once imported, other runspaces have no idea what changes you've made. Complications like this are one of the pitfalls of runspaces, but, if you need a bunch of quick tasks to run in parallel, it's a worthy pitfall : )
      Anyhow! With that in mind, your first sample of code isn't sending any output.  Invoke-Parallel will output anything that you write to the pipeline, whether you use Write-Output, Return, or any other means.
      So, in your example, starting after the # Get a list of Share host uris comment, all you really need is:
      ([regex]::matches($innerHTML, $using:matchstr) | %{$_.value})
      You don't need to save that to a variable if all you want to do is output it.
      All PowerShell works this way, whether you use Invoke-Parallel, Foreach-Object, Foreach, write your own function, etc.  If you don't send output to the pipeline, you won't get output.
  • Parameter variable is not working
    2 Posts | Last post January 17, 2016
    • $date=get-date -Format yyMMddhhmm
      New-Item Y:\site_$date -Type Directory
      invoke-parallel -InputObject $server -ScriptBlock {$scriptblock} -Parameter $date
      $scriptblock = {
      robocopy "\\servername\site_$date /MT:100 /MIR  \\$server\D$\http /MT:100 /MIR} 
      Date parameter value is not being taken in the script block.
    • Hi Antony!
      Unfortunately, Invoke-Parallel doesn't know the variable name you're passing in to -Parameter, so rather than using $Date in the scriptblock, you would need to use $Parameter:
      $date = get-date -Format yyMMddhhmm
      New-Item Y:\site_$date -Type Directory
      invoke-parallel -InputObject $server -Parameter $date {
          # I replaced $Date with $Parameter
          # Also, each InputObject ($Server) is $_
          #    $Server won't work in the scriptblock unless you define it manually
          #    Similar to Foreach-Object or Where-Object
          robocopy "\\servername\site_$parameter /MT:100 /MIR  \\$_\D$\http /MT:100 /MIR
      Keep in mind, you can always check this stuff before running the actual command:
      $date = get-date -Format yyMMddhhmm
      $server = 'server1', 'server2'
      invoke-parallel -InputObject $server -Parameter $date {
          "`$Date is $Date"
          "`$Parameter is $Parameter"
          "`$Server is $Server"
          "`$_ is $_"
      This gives the output:
      $Date is 
      $Parameter is 1601171058
      $Server is 
      $_ is server1
      $Date is 
      $Parameter is 1601171058
      $Server is 
      $_ is server2
1 - 10 of 17 Items