Pipeline – How is it Received and Handled

In the previous section we looked at piping output to another command, we used it mainly to format the output of a command but we also looked briefly at how we might take an action based on the output by using the command

Get-Process -ProcessName ‘Notepad’ | stop-process

This gets the process ID for the process with the name ‘Notepad’ and passes it into the stop-process command, but how do we know that the stop-process command can accept pipeline input and that this input has to be a process id? Here we go back to lesson 3 – getting help.

If you run the command Get-Help Stop-Process -Full you will get a fairly large and complex output but in the middle of it, each accepted parameter is listed with its type and whether or not it can be receive input from the pipeline. In the screen shot below we see an excerpt from this output that demonstrates that Id and InputObject can be piped into the command.

Screen capture showing an excerpt of the output of Get-Help for Stop-Process

ByValue

We can also send the output to the command without telling it what is coming. When a property accepts pipeline input ByValue then PowerShell will attempt to match the values passed to it and assign them accordingly. In this case Stop-Process only has the single property -InputObject that supports ByValue . Let us look a bit closer at how this works.

Get-Process is used to gather information and the output of that command is sent along the pipeline as input to the Stop-Process cmdlet. Get-Process has an output type of System.Diagnostics.Process and the -InputObject property of Stop-Process requires an input type of System.Diagnostics.Process. How do we know this?Here we introduce another command you will come to rely on, it is Get-Member.

Get-Member

You can also use the alias gm. If we pipe a fully formed cmdlet into Get-Member we then get an output similar to the screen capture below (NOTE: this has been concatenated for ease of reading). You can see all the parameters, attributes and lots of other information a command requires or produces using this command.

Screen capture showing an excerpt of the get-Member command for Get-Process

As you can see here, we have a list of members of various types from aliases, events, methods and properties… cut of from this output is also a MemberType named ScriptProperty… what we are most interested in for this tutorial though is the very first line of output that shows the TypeName is System.Diagnostics.Process – this is the object type output.

So now we know what the output type is and what we will be passing along the pipeline, it will be output of type System.Diagnostics.Process

Will Stop-Process accept this? Lets look again at the output of the Get-Help we ran earlier for Stop-Process

Note the highlight this time shows the property -InputObject and as this is a property that accepts pipeline input, the type next to it is the type of input it requires, in our case System.Diagnostics.Process. The [ ] indicate it will accept an array of that type if necessary.

So we have established that the output of Get-Process is System.Diagnostics.Process and that Stop-Process can accept that as input through -InputObject how does it know to assign it to that? Well that comes down to the ByValue input.

Powershell will attempt to assign the output of the command to an input of the next command, it will attempt to do it by Value. The first parametr that accepts input of the type System.Diagnostics.Process will be the one that gets the input of that type. In our case it is the ONLY one that accepts it and the only one that accepts input ByValue

ByPropertyName

If PowerShell cannot assign pipeline input ByValue it will attempt to do so by ByPropertyName.

PowerShell will attempt to match a property of the object passed to a parameter of the command. This match occurs in its simplest form, if the object has a property “Id” it will be matched with the parameter “Id” because they are spelled the same. This can lead to unexpected results, especially with more common properties and parameters such as “Name”.

Consider this:

Your aim is to stop running processes but in error you type:

get-service | stop-process

get-service does not have any output of type System.Diagnostics.Process so assigning ByValue won’t work, however it does have a property with an alias of Name, so PowerShell will attempt to assign that ByPropertyName

On Windows 10 you could try this example:

get-service XblAuthManager | Stop-Process

The output you get should be an error, but the error comes from the Stop-Process command because it cant find a process named XblAuthManager

Whilst not perfectly clear, it does demonstrate that PowerShell has matched the name from Get-Service with the Name in Stop-Process and so Stop-Process has attempted to stop a process named XblAuthManager but failed because there wes no such process.