Run a PowerShell script multi-threaded. I mean in parallel!

Have you ever wanted to run a PowerShell script in parallel?

Here is a functions that I created to run a script in parallel or multi-threaded.

Invoke-ScriptMultiThreaded.ps1 has been uploaded to the TechNet Script Repository here:

I want to give a shout out to the SCOO'er at Ramstein AB Germany for their outstanding dedication and work.

Hope this PowerShell helps!

Note:  There error handling puts an EventID 100 in the Windows PowerShell event log.  It will capture the last error thrown.


Function Invoke-ScriptMultithreaded{

 <#
  .SYNOPSIS
  This function is for running a PowerShell script in multiple threads simultaneously.
  .DESCRIPTION
  The function requires an array of at least one element to work properly.  The Foreach statement will parsed the array into elements and feed them into individual jobs.
  The element will be the first argument in the script.  The Arguments parameter is used for any arguments (up to 21) that the script requires to run. 
  .PARAMETER Script
  The Script parameter is the file path and PowerShell script that will be run.
  .PARAMETER Arguments
  The Arguments parameter will feed up to 21 variables as input for the PowerShell script. 
  The Arguments parameter should be an array with the elements in the same order as the invoked scripts parameters.
  The Arguments parameter is not required.
  .PARAMETER Array
  The Array parameter is an array of elements that will be used as input for the script. An example would be an array of computer names.
  .EXAMPLE
  Invoke-ScriptMultithreaded -Script ".\Test-Ping.ps1" -Array $Computers
  
  Description
  -----------
  The PowerShell script that will be invoked must be the first parameter. The Array parameter must have at least one element.
  .EXAMPLE
  Invoke-ScriptMultithreaded -Script ".\Test-Ping.ps1" -Arguments $Arguments -Array $Computers
  
  Description
  -----------
  The Arguments parameter must be an array with the elements in the same order that the invoked script requires.
  .EXAMPLE
  Get-ADComputer -SearchBase "OU=Computers,DC=CONTOSO,DC=Local" -Filter '*' | Select-Object -ExpandProperty Name | Invoke-ScriptMultithreaded -Script .\Test-Ping.ps1 $Arguments
  
  Description
  -----------
  The Invoke-ScriptMultithreaded function can use objects that are piped in from other commands for the Array.
  The Arguments parameter does not have to be used or defined when piping objects.
  .INPUTS
  This function requires that a PowerShell script and at least one array object be provided.
  IMPORTANT:  The PowerShell script that will be invoked must require the array object as its first parameter.
  .OUTPUTS
  This function creates a job or PowerShell process for each element defined in the array parameter.
  .NOTES
  Invoke-ScriptMultithreaded
  Advanced function for running a PowerShell script multiple times in parallel
  Author: Robert Gullick
  Creation Date: 7/01/2016
  Modified Date: 7/20/2016
  Version: 1.0.0
  .LINK
  https://blogs.technet.microsoft.com/rgullick/
  https://blogs.technet.microsoft.com/rgullick/2017/01/10/run-a-powershell-script-multi-threaded-i-mean-in-parallel
  https://gallery.technet.microsoft.com/scriptcenter/Run-a-PowerShell-script-991c8a42
  .COMPONENT
  No additional components are required for this script to run.  However, the invoked script may need modules loaded or other components to work properly.
  .ROLE
  No elevated permissions are required for this script to run.  However, the invoked script may require elevated permissions for work properly.
  .FUNCTIONALITY
  This function is designed to run a script multiple time in parallel and in separate worker processes.  Each invoked script will have its own process and memory.
#>

  [cmdletbinding()]
  param(  
    [Parameter(Mandatory=$true,ValueFromPipeline=$false)]
    [String]$Script,
    [Parameter(Mandatory=$false,ValueFromPipeline=$false)]
    [String[]]$Arguments,
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [Object[]]$Array
    )
    BEGIN{
    If($Arguments -eq $NULL){$Arguments = @()}
    $a = $Arguments   # This is to make the script more readable
     } # end BEGIN
    
    PROCESS{
        Foreach($Element in $Array){
            try{
            Start-Job -name $Element -FilePath $Script -ArgumentList $Element, $a[0], $a[1], $a[2], $a[3], $a[4], $a[5], $a[6], $a[7], $a[8], $a[9], $a[10], $a[11], $a[12], $a[13], $a[14], $a[15], $a[16], $a[17], $a[18], $a[19], $a[20]
            } #end try
            catch{
            $Exception = $error[0]
            $FunctionError =    "`r`n" + "Function:"  + "`t"   + "Invoke-ScriptMultithreaded " + 
                                "`r`n" + "Script:"    + "`t`t" + $Script + 
                                "`r`n" + "Element:"   + "`t`t" + $Element + 
                                "`r`n" + "Arguments:" + "`t"   + $Arguments + 
                                "`r`n" + "Error:"     + "`t`t" + $Exception
            Write-EventLog -LogName "Windows PowerShell" -Source "PowerShell" -EventId 100 -Message $FunctionError -EntryType Error
            }#end catch
        }#end Foreach
    } #end PROCESS
    
    END {
    } #end END
}# end Function
 Function Invoke-ScriptMultithreaded{ 
<# 
  .SYNOPSIS 
  This function is for running a PowerShell script in multiple threads simultaneously. 
  .DESCRIPTION 
  The function requires an array of at least one element to work properly.  The Foreach statement will parsed the array into elements and feed them into individual jobs. 
  The element will be the first argument in the script.  The Arguments parameter is used for any arguments (up to 21) that the script requires to run.  
  .PARAMETER Script 
  The Script parameter is the file path and PowerShell script that will be run. 
  .PARAMETER Arguments 
  The Arguments parameter will feed up to 21 variables as input for the PowerShell script.  
  The Arguments parameter should be an array with the elements in the same order as the invoked scripts parameters. 
  The Arguments parameter is not required. 
  .PARAMETER Array 
  The Array parameter is an array of elements that will be used as input for the script. An example would be an array of computer names. 
  .EXAMPLE 
  Invoke-ScriptMultithreaded -Script ".\Test-Ping.ps1" -Array $Computers 
   
  Description 
  ----------- 
  The PowerShell script that will be invoked must be the first parameter. The Array parameter must have at least one element. 
  .EXAMPLE 
  Invoke-ScriptMultithreaded -Script ".\Test-Ping.ps1" -Arguments $Arguments -Array $Computers 
   
  Description 
  ----------- 
  The Arguments parameter must be an array with the elements in the same order that the invoked script requires. 
  .EXAMPLE 
  Get-ADComputer -SearchBase "OU=Computers,DC=CONTOSO,DC=Local" -Filter '*' | Select-Object -ExpandProperty Name | Invoke-ScriptMultithreaded -Script .\Test-Ping.ps1 $Arguments 
   
  Description 
  ----------- 
  The Invoke-ScriptMultithreaded function can use objects that are piped in from other commands for the Array. 
  The Arguments parameter does not have to be used or defined when piping objects. 
  .INPUTS 
  This function requires that a PowerShell script and at least one array object be provided. 
  IMPORTANT:  The PowerShell script that will be invoked must require the array object as its first parameter. 
  .OUTPUTS 
  This function creates a job or PowerShell process for each element defined in the array parameter. 
  .NOTES 
  Invoke-ScriptMultithreaded 
  Advanced function for running a PowerShell script multiple times in parallel 
  Author: Robert Gullick 
  Creation Date: 7/01/2016 
  Modified Date: 7/20/2016 
  Version: 1.0.0 
  .LINK 
  https://blogs.technet.microsoft.com/rgullick/ 
  https://blogs.technet.microsoft.com/rgullick/2017/01/10/run-a-powershell-script-multi-threaded-i-mean-in-parallel 
  https://gallery.technet.microsoft.com/scriptcenter/Run-a-PowerShell-script-991c8a42 
  .COMPONENT 
  No additional components are required for this script to run.  However, the invoked script may need modules loaded or other components to work properly. 
  .ROLE 
  No elevated permissions are required for this script to run.  However, the invoked script may require elevated permissions for work properly. 
  .FUNCTIONALITY 
  This function is designed to run a script multiple time in parallel and in separate worker processes.  Each invoked script will have its own process and memory. 
#> 
 
  [cmdletbinding()] 
  param(   
    [Parameter(Mandatory=$true,ValueFromPipeline=$false)] 
    [String]$Script, 
    [Parameter(Mandatory=$false,ValueFromPipeline=$false)] 
    [String[]]$Arguments, 
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)] 
    [Object[]]$Array 
    ) 
    BEGIN{ 
    If($Arguments -eq $NULL){$Arguments = @()} 
    $a = $Arguments   # This is to make the script more readable 
     } # end BEGIN 
     
    PROCESS{ 
        Foreach($Element in $Array){ 
            try{ 
            Start-Job -name $Element -FilePath $Script -ArgumentList $Element, $a[0], $a[1], $a[2], $a[3], $a[4], $a[5], $a[6], $a[7], $a[8], $a[9], $a[10], $a[11], $a[12], $a[13], $a[14], $a[15], $a[16], $a[17], $a[18], $a[19], $a[20] 
            } #end try 
            catch{ 
            $Exception = $error[0] 
            $FunctionError =    "`r`n" + "Function:"  + "`t"   + "Invoke-ScriptMultithreaded " +  
                                "`r`n" + "Script:"    + "`t`t" + $Script +  
                                "`r`n" + "Element:"   + "`t`t" + $Element +  
                                "`r`n" + "Arguments:" + "`t"   + $Arguments +  
                                "`r`n" + "Error:"     + "`t`t" + $Exception 
            Write-EventLog -LogName "Windows PowerShell" -Source "PowerShell" -EventId 100 -Message $FunctionError -EntryType Error 
            }#end catch 
        }#end Foreach 
    } #end PROCESS 
     
    END { 
    } #end END 
}# end Function