Search code examples
powershellforeach

Powershell for each scripts not sequential


I have the following PowerShell for each statement that loops over a list of about 50 mailboxes and runs 2 scripts on each one. These 2 script take about a hour to complete. Because of the sequential nature of PowerShell this would take ~50 mailboxes * 1 hour = 50 hours.

Is it possible for PowerShell to run the script on each mailbox on the same time, in parallel?

Foreach($mailbox in $mailboxes){
    Write-Host "$(Get-TimeStamp) Start of adding contacts $mailbox"
        & $scriptPath -Mailbox  $mailbox.UserPrincipalName -ClientSecret $clientSecret -ClientID $clientID -TenantID $tenantID -CSVPath $csvPath
    Write-Host "$(Get-TimeStamp) Start of deduplicating contacts $mailbox"
        & $scriptPath2 -Mailbox  $mailbox.UserPrincipalName -ClientSecret $clientSecret -ClientID $clientID -TenantID $tenantID 
}

Solution

  • How about using the Start-Job?

    $jobs = @()
    
    foreach ($mailbox in $mailboxes) {
        $job1 = Start-Job -ScriptBlock {
            Write-Host "$(Get-TimeStamp) Start of adding contacts $mailbox"
            & $scriptPath -Mailbox  $mailbox.UserPrincipalName -ClientSecret $clientSecret -ClientID $clientID -TenantID $tenantID -CSVPath $csvPath
        }
    
        $job2 = Start-Job -ScriptBlock {
            Write-Host "$(Get-TimeStamp) Start of deduplicating contacts $mailbox"
            & $scriptPath2 -Mailbox  $mailbox.UserPrincipalName -ClientSecret $clientSecret -ClientID $clientID -TenantID $tenantID 
        }
    
        $jobs += $job1, $job2
    }
    
    # Wait for all jobs to finish and retrieve results (if any)
    $jobs | Wait-Job
    $jobResults = $jobs | Receive-Job
    
    # Clean up jobs and display results if needed
    $jobs | Remove-Job
    $jobResults