Warning: mysqli_result::fetch_assoc() expects exactly 0 parameters, 1 given in /var/www/powershellpower.com/public_html/page_parts/page.php on line 78

Warning: Use of undefined constant page_id - assumed 'page_id' (this will throw an Error in a future version of PHP) in /var/www/powershellpower.com/public_html/page_parts/page.php on line 92

Warning: Use of undefined constant synopsis - assumed 'synopsis' (this will throw an Error in a future version of PHP) in /var/www/powershellpower.com/public_html/page_parts/page.php on line 93

How to multithread scripts in powershell

One of the greatest things about powershell is it's ability to save you hours or manual labour administering servers and domain computers by creating automation scrips. Once we have mastered the art of automation in powershell we soon realise we could make the automation a thousand times faster if only we could multithread our scripts, and of course, we can.

6
Warning: mysqli_result::fetch_assoc() expects exactly 0 parameters, 1 given in /var/www/powershellpower.com/public_html/page_parts/page.php on line 156

Warning: Use of undefined constant text - assumed 'text' (this will throw an Error in a future version of PHP) in /var/www/powershellpower.com/public_html/page_parts/page.php on line 185
Import the 'Start_Multithread' module

Rather than spend time trying to create the mechanics for the multithreading the first task we have is to install a module called 'start-multithread' by Ryan Witschger. You can get the module from Ryan's blog here or cut and paste it from the window below and save it as a .PSM1 file and import it into powershell using the 'import-module' command. If you use the multi-thread script a lot (I am sure you will) please give thanks on Ryans blog page.


Param($Command=$(Read-Host"Enterthescriptfile"),
[Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]$ObjectList,
$InputParam=$Null,
$MaxThreads=20,
$SleepTimer=200,
$MaxResultTime=120,
[HashTable]$AddParam=@{},
[Array]$AddSwitch=@()
)

Begin{
$ISS=[system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$RunspacePool=[runspacefactory]::CreateRunspacePool(1,$MaxThreads,$ISS,$Host)
$RunspacePool.Open()

If($(Get-Command|Select-ObjectName)-match$Command){
$Code=$Null
}Else{
$OFS="`r`n"
$Code=[ScriptBlock]::Create($(Get-Content$Command))
Remove-VariableOFS
}
$Jobs=@()
}

Process{
Write-Progress-Activity"Preloadingthreads"-Status"StartingJob$($jobs.count)"
ForEach($Objectin$ObjectList){
If($Code-eq$Null){
$PowershellThread=[powershell]::Create().AddCommand($Command)
}Else{
$PowershellThread=[powershell]::Create().AddScript($Code)
}
If($InputParam-ne$Null){
$PowershellThread.AddParameter($InputParam,$Object.ToString())|out-null
}Else{
$PowershellThread.AddArgument($Object.ToString())|out-null
}
ForEach($Keyin$AddParam.Keys){
$PowershellThread.AddParameter($Key,$AddParam.$key)|out-null
}
ForEach($Switchin$AddSwitch){
$Switch
$PowershellThread.AddParameter($Switch)|out-null
}
$PowershellThread.RunspacePool=$RunspacePool
$Handle=$PowershellThread.BeginInvoke()
$Job=""|Select-ObjectHandle,Thread,object
$Job.Handle=$Handle
$Job.Thread=$PowershellThread
$Job.Object=$Object.ToString()
$Jobs+=$Job
}

}

End{
$ResultTimer=Get-Date
While(@($Jobs|Where-Object{$_.Handle-ne$Null}).count-gt0){

$Remaining="$($($Jobs|Where-Object{$_.Handle.IsCompleted-eq$False}).object)"
If($Remaining.Length-gt60){
$Remaining=$Remaining.Substring(0,60)+"..."
}
Write-Progress`
-Activity"WaitingforJobs-$($MaxThreads-$($RunspacePool.GetAvailableRunspaces()))of$MaxThreadsthreadsrunning"`
-PercentComplete(($Jobs.count-$($($Jobs|Where-Object{$_.Handle.IsCompleted-eq$False}).count))/$Jobs.Count*100)`
-Status"$(@($($Jobs|Where-Object{$_.Handle.IsCompleted-eq$False})).count)remaining-$remaining"

ForEach($Jobin$($Jobs|Where-Object{$_.Handle.IsCompleted-eq$True})){
$Job.Thread.EndInvoke($Job.Handle)
$Job.Thread.Dispose()
$Job.Thread=$Null
$Job.Handle=$Null
$ResultTimer=Get-Date
}
If(($(Get-Date)-$ResultTimer).totalseconds-gt$MaxResultTime){
Write-Error"Childscriptappearstobefrozen,tryincreasingMaxResultTime"
Exit
}
Start-Sleep-Milliseconds$SleepTimer

}
$RunspacePool.Close()|Out-Null
$RunspacePool.Dispose()|Out-Null
}



Warning: Use of undefined constant text - assumed 'text' (this will throw an Error in a future version of PHP) in /var/www/powershellpower.com/public_html/page_parts/page.php on line 185
Create an array of computers

Now we have our 'Start-Mutlithread' module in place we can test how the multi threading works. In this example we will create a list of computers to perform the task on


$list = "server1","server2","server3"



Warning: Use of undefined constant text - assumed 'text' (this will throw an Error in a future version of PHP) in /var/www/powershellpower.com/public_html/page_parts/page.php on line 185
Start the multithread script

The first line of our script starts the multithread operation. The ($computername) variable is going to pull the name from our list, it is important to know this in order to script this correctly


Start-Multithread -Script {param ($computername)



Warning: Use of undefined constant text - assumed 'text' (this will throw an Error in a future version of PHP) in /var/www/powershellpower.com/public_html/page_parts/page.php on line 185
Transfer the computer name to a new variable

I prefer to get the name from the $computer variable into a new variable but this isn't neccesary, you can go ahead and use the $computer variable as you wish but just know that in each thread the $computer variable will be unique to every other running thread


$computer = $computername



Warning: Use of undefined constant text - assumed 'text' (this will throw an Error in a future version of PHP) in /var/www/powershellpower.com/public_html/page_parts/page.php on line 185
Create the script tp perform on each machine in the list

Here we compose the script we would like to perform on each computer in our list, I have just used a simple start-service command here, but you can make the script as complex as you like


Get-Service -Name WinRM -ComputerName $computer | Start-Service



Warning: Use of undefined constant text - assumed 'text' (this will throw an Error in a future version of PHP) in /var/www/powershellpower.com/public_html/page_parts/page.php on line 185
The final piece

The final piece to the puzzle is to close the script, it requires two further pieces of information here.
1. Tell the script where we will be getting out list of computers from, so in this example $list
2. How many threads we want to run at any one time.
I have tried this with 50 threads and it worked perfectly, I am not sure how many it can technically cope with but Ryan's example showed 200 threads!.


} -ComputerName $list -MaxThreads 200


Comments

Notice: Undefined variable: commentno in /var/www/powershellpower.com/public_html/page_parts/page.php on line 335
// Collect comments ''
Fatal error: Uncaught Error: Call to a member function fetch_assoc() on bool in /var/www/powershellpower.com/public_html/page_parts/comments.php:9 Stack trace: #0 /var/www/powershellpower.com/public_html/page_parts/page.php(343): include() #1 /var/www/powershellpower.com/public_html/pages/how_to_multithread_scripts_in_powershell.php(2): include('/var/www/powers...') #2 {main} thrown in /var/www/powershellpower.com/public_html/page_parts/comments.php on line 9