It looks like there are more and more
ForEach-related topics coming out of blogosphere. This time I came across this post by Matthew Byrd on Exchange PowerShell behavior. In the post he compares two versions of Exchange 2007 one-liners: one with
ForEach-Object and the other with direct pipelining. He then notices that the one with
ForEach-Object is much faster:
The reason for this is simple and is tied into how PowerShell executes commands that are pipelined together. PowerShell executes the commands in a linear manner. So it will execute completely the first command in then pass the whole output to the next command in the pipeline. That means that if you have 30,000 mailboxes in your org and you run the shorter command you must enumerate all 30,000 mailbox objects before you pass it down the pipeline.
I am not sure this is PowerShell behavior really. Please correct me if I am wrong but I was under impression that if the left-hand cmdlet is using
WriteObject(object, true) this cmdlet sends objects into the pipeline one at a time, and if the right-hand side processes the objects in
ProcessRecord method, then all processing should be happening asynchronously and not after the first cmdlet is fully done.
So apparently something is not working “as designed” and either Exchange cmdlets are not using the interfaces right, or PowerShell v1 is not working “as advertised” (and using some undocumented “secret hooks” internally to make
foreach-object, and other built-in cmdlets work with pipeline correctly – one object at a time).
Which actually does not change the outcome I guess: with Exchange 2007
ForEach-Object can be much more efficient than direct pipelining. Check your script performance – PowerShell gives you tons of ways to do the same thing and, as Matthew reports, some ways can be better than others!
But still, if you know whose issue this is please leave a comment. Maybe we need to post another CR to Microsoft Connect here…