Is there a better way in Powershell to handle multiple levels of returned values than nested foreach
loops?
I need to get a list of each of our Azure Virtual Desktop session hosts for further processing. This requires me to iterate over a list of resource groups to get the host pool(s) in each of them; iterate over those to get the session hosts within each; and finally iterate over the session hosts:
foreach ($resourceGroup in $resourceGroups) {
$hostPoolObjects = Get-AzWvdHostPool -ResourceGroupName $resourceGroup.ResourceGroupName
foreach ($hostPool in $hostPoolObjects) {
$sessionHosts = Get-AzWvdSessionHost -ResourceGroupName $resourceGroup.ResourceGroupName -HostPoolName $hostPool.Name
foreach ($sessionHost in $sessionHosts) {
# Further processing
}
}
}
That seems inefficient. and, knowing how many session hosts I’m dealing with, memory intensive. Is there another method I could be using? I’m looking into whether multithreading would help in any way; maybe for the foreach ($hostPool in $hostPoolObjects)
block.
2
Answers
There is a way you can reduce 1 of the loops by using a Resource Graph query (
Search-AzGraph
). This example gets all Host Pools with their corresponding Resource Group and Subscription:From there if you need faster processing you could use
ForEach-Object -Parallel
instead but you need PowerShell 7+ for that:If you’re stuck with Windows PowerShell you can have a look at this Q&A and this module.
Fundamentally, you can take advantage of the PowerShell pipeline‘s auto-enumeration behavior and the ability of most cmdlets to accept object-by-object input via the pipeline:
Note:
The above invariably performs sequential object-by-object processing.
In PowerShell (Core) 7, you can speed up processing with parallel processing, using the
ForEach-Object
cmdlet’s-Parallel
parameter; as noted in Santiago’s answer, alternative solutions are available in Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1).