So, I had a scenario the other day where I wanted to run a PowerShell script on approximately 300 remote computers in an outage windows of no more than 30 minutes. The challenge was the script took 2 minutes to complete. I didn’t have enough fingers and toes for the math, so used a calculator to determine it would be… 600 minutes. Hmm, last time I checked 600 minutes is more than 30. So what to do..
The only way I could see this getting across the line was doing things in parallel. At 2 minutes per computer, I would need… give me a second… 20! batches of 15 computers. That would allow me to knock it out in 30 minutes. Well that was great, how was I going to do that? Also, with all things I do, I wanted to make the script reusable.
Now there are numerous ways to attack this, PowerShell workflows or jobs for example, but I also wanted to see output on screen as it was running. So I needed to launch separate PowerShell consoles for each of my batches of scripts. Without further ado here is what was cobbled together:
# Take a few parameters
# ComputerName - 1 or more computers (obviously pass more than one! or whats the point??)
# ScriptPath - Path to the PS1 powershell script you want to execute
# Batches - Number of Computers you want to pass to each Powershell script specified (default 10)
function Start-MultipleScriptExecution ($ComputerName, $ScriptPath, $Batches=10)
#Break the passed Computers into their batches
for ($i = 0; $i -lt ($ComputerName.Length)/$Batches; $i++)
#Create an array to hold the computers in each batch
$Batch = @()
for ($j = 0; $j -lt $Batches; $j++)
# Get index of computer to retrieve from array
$index = ($Batches * $i) + $j
# Ensure index is not greater than array length
if ($index -lt $ComputerName.Length)
#add computer to batch
$Batch += $ComputerName[$index]
# Join the batch array of computers together with commas
$BatchArg = [String]::Join(",",$Batch)
# Create arguments, NOTE the script that is called needs to load an argument
# called "Batch" that will contain the computers in it's batch
$args=" -NoExit -File $ScriptPath -Batch $BatchArg"
# Start new instance of Powershell with given computers and do it all again (i.e. loop)
Start-Process "powershell.exe" -ArgumentList $args
# Job Done
Enjoy, pretty hacky, but that’s the way i roll!