Search code examples
functionpowershellparameterspipeline

Powershell function: weird difference between pipeline and common parameter value


i am getting confused by the way powershell deals with function parameters.

so i have this sample ps module i made just for testing purposes, based upon my real script:

function test {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')]

param(
    [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [System.Management.Automation.PSObject]$InputObject
)

Begin {
}
Process {
Write-Host $InputObject
}
End {
}
}

Export-Modulemember -function test

save it as test.psm1 & import, and do 2 tests:

First Test:

(get-process | select -first 5) | test

will return with this:

System.Diagnostics.Process (7zFM)
System.Diagnostics.Process (7zFM)
System.Diagnostics.Process (AcroRd32)
System.Diagnostics.Process (AcroRd32)
System.Diagnostics.Process (AESTSr64)

Second Test:

test -InputObject (get-process | select -first 5)

will instead return with this:

System.Diagnostics.Process (7zFM) System.Diagnostics.Process (7zFM) System.Diagn
ostics.Process (AcroRd32) System.Diagnostics.Process (AcroRd32) System.Diagnosti
cs.Process (AESTSr64)

same happens when i use a variable to store and forward the data.

there seem to be a difference in the way powershell treats parameters, the data i get back when using the -InputObject parameter seem to loose its array-ish format in some way...

why does it do that? and is there a way to change this behaviour?


Solution

  • The Powershell pipeline automatically "unrolls" arrays and collections one level, and passes them on to the next cmdlet or function one at a time, so when you send that array through the pipeline your function is dealing with one process object at a time.

    When you use the parameter, you're sending the entire array at once, and your function is dealing with an array object, not a process object, so you get different results.

    Try this and see if it doesn't make a difference in your output:

    Process {
     $InputObject | foreach {Write-Host $_ }
    }