Parallel Task Execution for ILM/FIM using PowerShell

Last year, I wrote about how I would use VBScript to execute run profiles in ILM/FIM in parallel (mixed with some serial syncs since they don’t behave well when run in parallel). I’ve now created, with the help of a few friends and other TechNet/MSDN authors, a PowerShell script that will do the trick. It performs the same task without the need of the ugly GUIDs in the old VBScript exports, and without a script per run profile. In other words, it’s one easy-to-read file.

Since PowerShell has a bit more flexibility, we can reference the MA by running a query based on the name instead of being forced to use the GUID. This makes the script more readable. Also, the “Start-Job” command allows us to launch several threads in parallel, while waiting for them to finish with a “Wait-Job”.

Below is a generic version of the script (there are some coding artifacts since it is Frankensteined from multiple sources, but it works):

############
# PARAMETERS
############

$params_ComputerName = "." # "." is the current computer
$params_delayBetweenExecs = 5 #delay between each execution, in seconds

############
# FUNCTIONS
############

function Run-MA
{PARAM([string]$maName,[string]$runProfile)
$MAs = @(Get-WmiObject `
-class "MIIS_ManagementAgent" `
-Namespace "root\MicrosoftIdentityIntegrationServer" `
-ComputerName ".")

   foreach($MA in $MAs)
{
if($MA.Name.Equals($maName))
{
$result = $MA.Execute($runProfile)
}
}
}

$SynchronousRun = {function Run-MAsynchronous
   {PARAM([string]$maName,[string]$runProfile)
      $MAs = @(Get-WmiObject `
      -class "MIIS_ManagementAgent" `
      -Namespace "root\MicrosoftIdentityIntegrationServer" `
      -ComputerName ".")
      $maNameArray = $maName.split(",")
      foreach($singleMA in $maNameArray)
      {
         foreach($MA in $MAs)
         {
            if($MA.Name.Equals($singleMA))
            {
               $results = $MA.Execute($runProfile)
            }
         }
      }
   }
}

############
# PROGRAM
############

start-job {Run-MAsynchronous -maName "FIM MA" -runProfile "Delta Stage"} -InitializationScript $SynchronousRun
Start-Job {Run-MAsynchronous -maName "AD MA" -runProfile "Delta Stage"} -InitializationScript $SynchronousRun
start-job {Run-MAsynchronous -maName "AD LDS MA" -runProfile "Delta Stage"} -InitializationScript $SynchronousRun

Get-Job | Wait-Job

Run-MA -maName "FIM MA" -runProfile "Delta Sync"
Run-MA -maName "AD MA" -runProfile "Delta Sync"
Run-MA -maName "AD LDS MA" -runProfile "Delta Sync"

start-job {Run-MAsynchronous -maName "FIM MA" -runProfile "Export"} -InitializationScript $SynchronousRun
start-job {Run-MAsynchronous -maName "AD MA" -runprofile "Export"} -InitializationScript $SynchronousRun
start-job {Run-MAsynchronous -maname "AD LDS MA" -runProfile "Export"} -InitializationScript $SynchronousRun

Get-Job | Wait-Job

Please remember that these lines above are wrapped.

You can see that the PROGRAM section is where the action happens. In it, I launch three MAs which run simultaneous imports, then the script waits for those to complete and runs the next three lines (Delta Sync profiles in my case) in serial. After the last line is complete, it spawns another set of simultaneous, or asynchronous exports and then the script is complete.