PowerShell 7 and the Difference in ForEach, ForEach-Object and ForEach-Object -Parallel

Here is another guest post by Gourav Kumar he submitted a little bit earlier when PowerShell 7 just came out. He talks about some of the differences between the versions and command results. Enjoy:


I have just installed the new PowerShell 7 on my system and I am curious to see how new things just changed the time-complexity.

So first I have to launch a new PowerShell, which now we could do using pwsh in the search bar (I am using Windows 10). But we have to keep in mind PowerShell 5 can’t be opened by typing pwsh in search, Its same PowerShell search.
Have a look below screenshots as I am using both PS5 and PS7 on my system.

Screenshots for PowerShell 7: –

Screenshots for PowerShell 5: –

Now it’s time to just jump into writing about new features regarding reducing time complexity.
And for this ForEach, ForEach-Objet and ForEach-Object -Parallel is best to learn and see things in real world.

To demonstrate this I have created 3 simple script blocks for Azure VMs. The end goal of these scripts is to provide a similar output (VM name, Resource Group Name of the VM).
I have used 3 different methods to check how they are different from each other when it comes to working. To find this out I need to use some other PowerShell feature to determine things and then I realized Measure-Command is the best buddy here ?

Now I have everything on my plate and its’ time to cook the food for final craving.

First and Foremost, I am going to write a code block for my favorite ForEach,

$RGS = (Get-AzResourceGroup).ResourceGroupName
ForEach($RG in $RGS)
Get-Azvm -ResourceGroupName $RG | Select Name, ResourceGroupName

Now its’ time for ForEach-Object

Get-AzResourceGroup | ForEach-Object {
Get-AzVM -ResourceGroupName $_.ResourceGroupName | Select Name, ResourceGroupName }

And finally we have -Parallel block, this is the new feature of PowerShell that creates workflow parallelly in memory.

Get-AzResourceGroup | ForEach-Object -Parallel {
Get-AzVM -ResourceGroupName $_.ResourceGroupName | Select Name, ResourceGroupName }

Now we are all set with the scripts blocks, it is time for testing and measuring the time taken by the scripts.
Measure-Command will help us with their timings to understand how much time it has taken to run the script blocks.
Below are the screenshots for all the 3 scripts and we all could see the difference in their execution time.
Screenshots for ForEach : –

Screenshots for ForEach-Object : –

Screenshots for ForEach-Object -Parallel : –

And we can see the clear winner is ForEach-Object -Parallel with its only 18 seconds timing.
Conclusion, whenever we have multiple things to do, now we need to use the new Parallel workflow to get the things done smooth and easily in less time.

Thank you for your blog post Grav! Enjoy scripting!