Skip to content

Instantly share code, notes, and snippets.

@JustinGrote
Created February 9, 2022 22:05
Show Gist options
  • Save JustinGrote/229b5aa502552058fabfbb2417d6c6b8 to your computer and use it in GitHub Desktop.
Save JustinGrote/229b5aa502552058fabfbb2417d6c6b8 to your computer and use it in GitHub Desktop.
Run Exchange Commands in Parallel
#requires -module ExchangeOnlineManagement,ThreadJob
function Start-ExchangeThreadJob {
<#
.SYNOPSIS
Works like Start-Threadjob but for Exchange and preserves the exchange state
.NOTES
This works because the new REST commands are basically CLIXML proxies via a REST API. A dynamic module is generated upon
connection to the exchange server, and it has the session context and token "hard coded" into the module.
By simply bringing this module into the runspace, it shares the same context and token.
#>
[CmdletBinding()]
param(
[ScriptBlock]$ScriptBlock,
[Parameter(ValueFromPipeline)]$InputObject,
[Int]$ThrottleLimit = 10
)
begin {
#Fetch the Exchange REST autogen module.
#TODO: Better matching?
[string]$GLOBAL:restModulePath = Get-Module tmp*
| Where-Object Description -EQ 'This is a Powershell module generated by using the AutoGEN infra.' #HACK: Need better way to identify
| Select-Object -Last 1 #Multiple modules can be created, get the latest one
| ForEach-Object Path
if (-not $restModulePath) {
throw 'Could not find the Exchange REST module. You must run Connect-ExchangeOnline before using this command.'
}
#HACK: Cannot use $USING with InitializationScript, append the command to the main scriptblock as a workaround.
#https://github.com/PowerShell/PowerShell/issues/4530
[ScriptBlock]$scriptBlockToRun = [ScriptBlock]::Create(
[string] { Import-Module $USING:restModulePath -Verbose:$false } +
[Environment]::NewLine +
[String]$ScriptBlock
)
$startThreadJobParams = @{
ThrottleLimit = $ThrottleLimit
InitializationScript = {
Import-Module ExchangeOnlineManagement -Verbose:$false
}
ScriptBlock = $scriptBlockToRun
}
$i = 1
}
process {
$InputObject | Start-ThreadJob -Name "ExchangeThreadJob$i" @startThreadJobParams
$i++
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment