I just posted an article to the FAQ on the PoshCode Wiki answering this question that came up again on our IRC PowerShell user group today. It came up in the context of determining whether a function was the last function on the pipeline, because one of our users was looking for a way (other than creating ps1xml files) to output objects onto the pipeline for use in other functions, but still format those objects nicely if they were output directly.
Before I give the solution, I just want to say: don’t change your output based on where you are in a pipeline.
There are numerous scenarios where your function will be the last one on a pipeline, but still be participating in further pipelines, including formatting and output modification. For example, take our function Test-Pipeline (defined below) in these three scenarios below. In none of these scenarios would it be appropriate for the function to write formatted output instead of outputting the raw object, but in each case, the function is the last function in the pipeline.
# Assignment
$order = Get-ChildItem | Test-Pipeline
$order | Format-Table *
# Nested Pipelines
Get-ChildItem | Where-Object { $_.PsIsContainer} | ForEach-Object {
Get-ChildItem $_ | Test-Pipeline
} | Select-Object Pipe*
# Nested Expressions
@( Get-ChildItem | Test-Pipeline )[0].PipelineLength | ForEach-Object { $_ }
However, if you want to determine your function’s position in the pipeline for some other reason, the answer is simple. You need to use $MyInvocation and compare the PipelineLength and PipelinePosition properties:
## Useful for testing all sorts of things about the pipeline
function Test-Pipeline {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline=$true)]
[PSObject]$InputObject,
[Switch]$Passthru,
[Switch]$PassCmdlet
)
BEGIN {
Write-Output $MyInvocation
if($PassCmdlet) {
Write-Output $PsCmdlet
}
}
PROCESS { if($Passthru){ $_ } }
}
## Shows
function Test-LastInPipeline {
Param(
[Parameter(ValueFromPipeline=$true)]
[PSObject]$InputObject,
[Switch]$Passthru
)
BEGIN {
$IsLast = $MyInvocation.PipelineLength -eq $MyInvocation.PipelinePosition
if(!$IsLast) { $MyInvocation }
}
PROCESS { if($Passthru){ $_ } }
}
![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=d70821bd-4e06-4fc1-81f4-451e14c63c2f)
[...] PowerShell: Determine your function’s position in the pipeline (Joel Bennett) [...]