Secret Script Block Parameters

by Mar 29, 2013

If you think you understand PowerShell parameter binding, then have a look at this simple function which exposes a little-known PowerShell behavior:

Function Test-Function
{
  param
  (
    [Parameter(ValueFromPipeline=$true)]
    [Int]
    $Number,

    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [Int]
    $Number2
  )

  Process
  {
    "Doing something with $Number and $Number2"
  }
} 

The function Test-Function accepts two parameters. Both can come from the pipeline. The first is accepting the entire pipeline input ("ByValue"), the second expects pipeline objects with a property "Number2" ("ByPropertyName"). So what do you think would happen when you call it like this:

Right: The numbers sent via pipeline go to parameter -Number, and the parameter -Number2 is always 6. That's what you'd probably have guessed.

However, when you submit a script block to -Number2, everything changes: PowerShell realizes that a script block is not an Integer. The call would have to fail with a type mismatch, but it doesn't. Instead, PowerShell happily accepts the script block and evaluates it, then takes its result as parameter value:

This is unexpected, yet very useful because it allows you to create parameters that dynamically process the data piped into the command. A lot of cmdlets use the very same technique.

Twitter This Tip! ReTweet this Tip!