Understanding PowerShell pipeline parameter binding

Undoubtedly, the most unique feature of PowerShell is its pipeline and it implements parameter binding. PowerShell allows us to pass objects (not just strings) across the pipeline. It must have a way to “map” various attributes from the command that’s outputting information to the command that needs that information as input. The method that does this is called parameter binding.

To demonstrate parameter binding, let's create our own simple example. We'll create a Get function and a Remove function. We will craft the Get function to return a specific object and its properties and then create the Remove function to understand these (bindings).

Demonstrating parameter binding ^

Notice in the example above that the Get-Widget function returns a type of pscustomobject with two properties: FileName and Path.

The Remove-Widget function has a single parameter called Widget that accepts an object type of pscustomobject.

When you run Get-Widget | Remove-Widget (which forces Remove-Widget to ingest whatever Get-Widget returns), you'll get this:

You can see Remove-Widget "sees" both properties because the entire object that Get-Widget returned was bound to $Widget. This type of binding is "binding by value." The entire object is bound to a parameter in the receiving command.

This doesn't just happen by itself though. This worked because of the ValueFromPipeline parameter attribute I've defined. This tells PowerShell to attempt to bind any appropriate object coming in from the pipeline to this parameter.

But what if you don't need the entire object to "map" to a parameter? Instead, perhaps you'd rather have only a single property represent a parameter on the receiving command. In such a case, we can set up binding by property. By setting a parameter to accept pipeline binding by property name, we can tell PowerShell to map only a single property of an object coming from the sending command to a parameter on the receiving command.

Using the same code for Get-Widget but changing the code for Remove-Widget a bit, we can change PowerShell's binding behavior. Notice below I've changed the $Widget parameter name to $Path in Remove-Widget, the type to string, and instead of using the parameter attribute ValueFromPipeline, I'm using ValueFromPipelineByPropertyName.

Parameter binding by property ^

If I've enabled strict mode by running Set-StrictMode -Version Latest, when I run this as is, it throws an error: The property 'FileName' cannot be found on this object. Verify that the property exists.

Unknown parameter binding behavior

Unknown parameter binding behavior

It's throwing this error because PowerShell didn't bind the entire object this time. Instead, it just bound the property name Path on Get-Widget's object. Under the hood, PowerShell is only attaching the value of Path to the $Path parameter.

I'll need to change up my Write-Host reference a bit now to use the Path variable (since it is the only thing bound) and run it again.

After running Get-Widget | Remove-Widget again, I now get no errors with the output Remove-Widget: I see the $Path parameter value is now C:\foo.txt. $Path's value now is the value of the Path property on the object that Get-Widget returned.

Conclusion ^

Parameter binding is a fascinating concept if you're a geek like me. If you're interested in learning more, check out exactly how both of these methods work. For further explanation on how the pipeline interacts with the begin, process, and end blocks, I highly recommend Boe Prox's blog article entitled Tips on Implementing Pipeline Support.

Join the 4sysops PowerShell group!

Your question was not answered? Ask in the forum!


Leave a reply

Your email address will not be published. Required fields are marked *


© 4sysops 2006 - 2020


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account