PowerShell

Understanding PowerShell Pipeline Parameter Binding

This write up should give you a basic understanding how pipeline objects are processed. The piping technique allows a kind of connection between commands. Piping is a key technologie in PowerShell. In this blog post I am going to have a look at the parameter binding on the “right side” of the pipe. In order to do this I will use the cmdlet Trace-Command to explore what’s going on when an object is passing the pipe from the left side to the right side. Let’s jump in.

Introduction

First of all, I give you a quick overview what is happening when you use piping. I’ve prepard a picture that shows the mechanism of the pipe in PowerShell.

Unbenannt.PNG

The question now is to which parameter of Stop-Process is the object of the pipe bound? Let’s examine which parameters support pipeline input. We can figure it out easily with Get-Help.


Get-Help Stop-Process -Parameter * | Where-Object pipelineinput -Like 'true*'

Unbenannt.PNG

Understanding PowerShell Pipeline Binding

Let’s first explore the most obvious way how PowerShell binds pipeline objects. PowerShell takes objects that come from on the left side of the pipe and then binds this objects to a parameter that accepts process objects.

For example, InputObject expects and accepts only process objects.


Get-Help Stop-Process -Parameter InputObject

1.png

This means that process objects are expected and that we need to provide this object on the left side of the pipe. PowerShell will then bind the process object to the parameter InputObject by value. The screen below shows the action.

unbenannt-1.png

Proof that this is really happening is provided by the Trace-Command cmdlet.


Trace-Command -Name ParameterBinding -Expression {Get-Process notepad | Stop-Process} -PSHost

unbenannt-1.png

Nice. The object on the left side of the pipe was bound to the InputObject parameter.

Next, let’s have a look at what is happening when the object that passes the pipe is not a process object …

1.PNG

The error message says …

The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipepline input.

Hey, that’s wrong! We actually have 3 parameters that accepts pipeline input … What’s going on here?

Remember, we have three parameters. None of them will be able to process the pipeline object ‘notepad’ and we will now see why. For clarifying let me show you the object type of ‘notepad’:

unbenannt-1

Notepad is a String.

Among other things, PowerShell tries to bind the argument to the Name parameter. However, the Name Parameter accepts only strings of Name objects. ‘notepad’ is not a Name Object. The picture below shows that it is as I prophesied it would be. Powershell will not try to bind the string to the Name parameter nor to the id parameter.


Trace-Command -Name ParameterBinding -Expression {'notepad' | Stop-Process} -PSHost

Unbenannt

How can we now make PowerShell accept the string (PSCostumObject) notepad? The answer is that we need to make Notepad a Name object.


$a=Get-Process -Name notepad | Select-Object -Property Name

Unbenannt.PNG

Note the difference between the current notepad object and the previous notepad object.

Unbenannt.PNG

Fine. Notepad’s property name now matches the parameter name “Name”.

Now we can pipe the object to Stop-Process.


$a | Stop-Process

Unbenannt.PNG

With Trace-Command we can check again what PowerShell has done. PowerShell has bound the pipeline object to the Name parameter because the pipeline object property name matches the “Name” parameter name.

1.PNG

I hope I could give a good insight into the topic and see you next time!

Links

https://devblogs.microsoft.com/scripting/learn-about-using-powershell-value-binding-by-property-name/

https://blogs.technet.microsoft.com/askpfeplat/2016/11/21/two-ways-to-accept-pipeline-input-in-powershell/

Categories: PowerShell

Tagged as: ,

8 replies »

  1. Hey Patrick. I don’t know if you can help me understand this or not but this post led me to investigate parameter binding in one of the commands I was trying to do which was failing. I can see where it’s failing (arg is null) and know how to make it work but I don’t understand why it doesn’t work as it is.

    The command is: $files | get-filehash -literalpath $_

    Where $files is a string array of file paths. The trace-command says that the $_ var is null. It also fails with get-filehash -literalpath ($_)

    However, it works with $files | get-filehash -literalpath {$_} which is including a script block. What is going on here?

    Thank you!! (Duplicate for email alerts)

    Like

  2. Hey Patrick. I don’t know if you can help me understand this or not but this post led me to investigate parameter binding in one of the commands I was trying to do which was failing. I can see where it’s failing (arg is null) and know how to make it work but I don’t understand why it doesn’t work as it is.

    The command is: $files | get-filehash -literalpath $_

    Where $files is a string array of file paths. The trace-command says that the $_ var is null. It also fails with get-filehash -literalpath ($_)

    However, it works with $files | get-filehash -literalpath {$_} which is including a script block. What is going on here?

    Thank you!!

    Like

  3. Nice one.. gave me a better insight into PS parameter binding and especially an into into the useful cmd Trace-Command.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.