Author Posts

May 6, 2013 at 5:47 pm

Get-Help ForEach-Object -full does not explain how the following example works.

PS C:\> 1..4 | ForEach-Object {'Begin'} {"Process $_"} {'End'}
Process 1
Process 2
Process 3
Process 4
PS C:\>

The -Begin and -End are named parameters, with a type of .

While -Process is listed as position 1.

To make things even more interesting, there is a new parameter for PS ver 3.0


Based on my interpretation of the help output, I would have expected the first scriptblock to be assigned to -Process, and the other two scriptblocks to flag some sort of syntax error. Is this a case where the actual behavior of the cmdlet is just not described well by the documentation conventions used?

Should I be concerned with cmdlet behavior with respect to parameter processing that does not seem to match the documentation?

Any insight would be appreciated.

May 7, 2013 at 7:56 am

Believe it or not, there is an explanation for this behaviour.

First, you should read this blog post:

Bartek explains what is actually happening here, and also shows you how Trace-Command can be used to see how parameters are bound.  This highlights how ForEach-Object internally evaluates whatever unbound script blocks you pass it and decides what to do with them based on whether or not you have explicitly provided -Begin or -End script blocks.

Regarding whether or not you should be concerned with cmdlet behaviour with respect to parameter binding not matching the documentation, I don't think you should be too concerned because this is a bit of an anomaly.  I would strongly recommend though that for actual scripts (as opposed to ad-hoc use of PowerShell) that you explicitly use named parameters because it removes any potential for confusion wrt parameter binding.

May 7, 2013 at 9:37 am

Amen on the named parameters. That said, it'd be nice if this was doc'd a bit better – and you should consider bugging it on Connect, so that MS can put some attention to it.