In this post we’ll take a look at how to perform parallel remote code execution with PowerShell. As a systems administrator, you often find yourself in the need of running PowerShell code against many servers. If you’re doing this by iterating through a foreach-loop, you’ll be waiting a long time for completion. This is because loops are sequencial, it runs against one computer at a time. One could use PowerShell jobs in order to start multiple background tasks which run in parallel, this is not the optimal approach. PowerShell jobs have extra overhead compared to .NET runspaces, they take longer to start. Runspaces on the other side, are more complex and not so intuitive, therefore most administrators stick to using PowerShell jobs.
In this post I’ll intoduce you to a script I wrote in order to simplify remote code execution against many systems, by using runspaces, not jobs. I have successfully used this script to run code against thousands of systems, in just a few minutes. It neatly provides an informational progressbar about how many jobs are queued, running or completed.
Modifying the Script
It would not make much sense to run the script as is. You’ll have to add the code you want to be run on the remote systems, and specify which systems to run against. The script is split into two regions, where you’ll only have to pay attention to the first region, CanModify.
You’ll have to specify the computers in the $Computers variable, either manually, by AD Organizational Unit (OU), or from a CSV file. You can conveniently just uncomment the OU or CSV line if you wish to use that method.
In the $Parameters hashtable you can save data that exists locally, in order to use it when the scriptblock is executed on the remote system. This is because scriptblock executed on the remote system does not have access to any of the resources on your local system.
Here’s where you’ll write the code you want to run on the remote computers. Add your code below the commment ## YOUR CODE BELOW. Note that you can access the variable $Parameters which you specified earlier in the script. You access it like you would with any hashtable.
Lastly, you can alter how many concurrent jobs can run by modifying the $JobLimit variable. It’s set to 30 by default, but will accept anything in the range 1 to 60. Be aware that increasing the limit can cause problems on the local system. If the local system is a weak computer, you may want to decrease the limit in order to limit the strain on the computer.
The script will return whatever you specify in the scriptblock $CodeBlock. If you intend to work with the result, you should store it in a variable like so:
$Result = .\Start-RemoteJob.ps1