Same reflection here, imho it would be much simpler to check with Get-ConnectionInfomation if we are already connected. Much less processing overhead and reduces the number of web requests by 50%.
However, tests show the connection is returned, even if it's made from another thread (which doesn't really make sense if the -Parallel thread is started as a different process).
A working trick is to use Test-Path to see if the cmdlet we need is available inside our thread (i.e. if we don't have a connection, we don't have the cmdlet).
Some more room for improvement here:
- Importing a CSV in an array in memory then processing each item in the array causes memory overhead, using the pipeline directly is much more efficient
- Explicitly specifying -UseMultithreading:$true for Connect-ExchangeOnline makes no sense, since this only applies to the *-EXO cmdlets, and $True is the default value anyway
- Connect-ExchangeOnline has this -CommandName switch, which allows you to only load the commands you need (in this case, just one), so this may significantly improve memory consumption
- Connect-ExchangeOnline defaults to WAM nowadays, which throws an error if it is called simultaniously (so we should add a -DisableWAM switch, or even better connect using an App & certificate and not an actual user)
- Disconnect-ExchangeOnline doesn't seem to make sense either, since we're connecting in a child process... Although it seems that somehow, the connection made in the child process is returned when calling Get-ConnectionInformation from the parent (so somehow the connection is seen by the parent process)
- Instead of setting the throttlelimit hardcoded to 5, you could use the number of cores to speed things up even more
try {
$Cores = Get-CimInstance CIM_ComputerSystem | Select-Object -ExpandProperty NumberOfLogicalProcessors
} catch {
$Cores = 5 # in case CIM call fails
}
Import-CSV C:\input_file_location.csv | ForEach-Object -Parallel {
if (Test-Path (Function:Set-MailboxJunkEmailConfiguration)) {
Connect-ExchangeOnline -UserPrincipalName "UPN" -DisableWAM -CommandName Set-MailboxJunkEmailConfiguration -DisableWAM -ShowBanner:$false
}
Set-MailboxJunkEmailConfiguration -Identity $_.identity -TrustedSendersAndDomains @{Add="email address removed for privacy reasons","email address removed for privacy reasons","email address removed for privacy reasons"
} -ThrottleLimit $Cores
Disconnect-ExchangeOnline -Confirm:$false
A few more remarks:
- 'Regular' ForEach-Process supports -Begin -Process -End parameters (similar to a function), it's a pity the pwsh devs didn't provide the same functionality when using -Parallel (this would be an excellent use case)
- Beware of throttling - EOM REST calls follow the Graph API throttling limits, so although you can now have more than 5 threads (as apposed to the 'old' PSSession to EXO), there's still some limits as to the number of requests you can throw at EXO/Graph within a given timeframe.
- Also be aware that you need at least PowerShell 7.1 for this to work correctly. The -parallel parameter is available in PS 7.0, but that version creates a new runspace for every iteration (basically meaning you would end up creating a new EXO connection for each individual row in the Excel)
[Update]
Looks like Get-ConnectionInformation inside the child thread doesn't work, so updated to use Test-Path instead