Using PowerShell Jobs for Parallel Execution

PowerShell is great and allows us to automate a bunch of tasks that would otherwise be repetitive and boring. Recently we’ve been investigating how to build a Microsoft Dynamics NAV environment (environment = SQL database, service tier and client) on demand on the local machine or separate SQL and NAV servers on the network.

Restoring the appropriate SQL backup, creating and configuring a service tier of the correct build and opening the correct client is all rather tedious and is ripe for some automation.

The details of how to build the environment isn’t really the subject of this post (maybe I’ll write about it one day) but how to make that process fast.

The sub-tasks of

  1. Restoring the SQL backup
  2. Obtaining the required object files from source control

can be relatively* time consuming, depending on how many objects need to be downloaded. However, there is no requirement for them to done in sequence. The whole process will be faster if we can do them at the same time.

We’re achieving this with a combination of sessions and jobs.

$Jobs = @()

$RestoreSQLScriptBlock = { [some code to restore the SQL backup] }
$SQLSession = New-PSSession $SQLServer
$Jobs += Invoke-Command –Session $SQLServer –ScriptBlock $RestoreSQLScriptBlock –AsJob
$CreateServerInstanceScriptBlock = { [some code to create NAV service tier] }
$NAVSession = New-PSSession $NAVServer
$Jobs += Invoke-Command –Session $NAVServer –ScriptBlock $CreateServerInstanceScriptBlock –AsJob
Write-Host 'Waiting for tasks to complete...'
Receive-Job $Jobs -Wait

If the above isn’t clear enough this is how it works:

  1. Create a $Jobs collection
  2. Create a script block variable to store the commands to execute on the target server(s)
  3. Create a remote PowerShell session on the target server(s)
  4. Use Invoke-Command to execute the script block in the remote session as a job and add the job details to the $Jobs collection
  5. Wait for all the jobs in $Jobs to complete before continuing with the rest of the script

Progress bars and output from the remote sessions are received by the parent session as it comes in. The remote server(s) need to be configured for PowerShell remoting, see Enable-PSRemoting.

Enjoy.

*tens of seconds. Longer than I’m prepared to wait – I’m impatient.

Leave a Reply