PowerShell Pipeline binding
To make your function accept pipeline input, mark a parameter [Parameter(ValueFromPipeline)] and put your work in a process block.
Documentation: Microsoft Learn
Overview
An advanced function can have three blocks. begin runs once before any input arrives, which is where you set up a counter or open a connection. process runs once per incoming object, and is where the actual work goes. end runs once after the last object, which is where you emit a summary.
The mistake that follows from not knowing this is putting pipeline work outside process. Code in the function body without a process block runs once, with the parameter holding only the last object that arrived. The symptom is a function that quietly processes one item out of fifty.
ValueFromPipelineByPropertyName is the other form. It matches an incoming object's property to your parameter by name, which is how Get-Service | Stop-Service works: the service objects have a Name property and Stop-Service has a -Name parameter.
Inspect this example’s structure
Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.
function Get-NameLength {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
[string] $Name
)
process {
[pscustomobject]@{
Name = $Name
Length = $Name.Length
}
} }
'Spooler' , 'BITS' , 'WinRM' | Get-NameLength- Stage 1function
Positional values or no named parameters - Stage 2Get-NameLength
Positional values or no named parameters
An example to inspect
Preview the example. Sign in for the full lesson and activities.
function Get-NameLength {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
[string] $Name
)
process {
[pscustomobject]@{
Name = $Name
Length = $Name.Length
}
} }
'Spooler' , 'BITS' , 'WinRM' | Get-NameLengthWhat happens
Three strings go into the pipeline. Because -Name is marked ValueFromPipeline and the work is inside process, the block runs three times and emits three objects. Remove the process block and you get one result for WinRM only, because the parameter ends up holding just the last value.
Worth remembering
- ValueFromPipeline binds the whole incoming object to the parameter.
- ValueFromPipelineByPropertyName matches by property name instead.
- process runs once per object. begin and end run once each.
- Pipeline work outside process silently handles only the last item.
Primary documentation
Try it
Illustrative output · values vary by environment
Example reader
Inspect this page's example
Run supported commands against the practice data, or inspect the example without executing it.
Ready to inspect.
A function that accepts pipeline input and runs once per object.
Show reference output
Illustrative output · values vary by environment
Name Length ---- ------ Spooler 7 BITS 4 WinRM 5
Keep going
Next: PowerShell try, catch and finallyCheck your understanding
An input object has a ComputerName property. When can a function bind that property automatically?
The parameter needs ValueFromPipelineByPropertyName and a matching name or alias, with a compatible value. By-value binding follows separate rules.