I've been trying to make my PowerShell script—not function— accept pipeline input, and I was surprised to see so much guidance on functions but not scripts. I figured it out but would be surprised if this is the best way.
Short answer: the magic word $input must be the name of the script's pipeline parmeter. That's it.
To illustrate, here is a simple script that generates objects (in the form of PSCustomObject) to be used by the script that consumes it.
# create_input.ps1 - produce test object values for Process-Favorites.ps1 $DATA = @( @( "Steve", "Orange" ), @( "Ben", "Blue" ), @( "Jaimee", "Green" ), @( "Kevin", "Pink" ), @( "Bob", "Purple" ) ) $DATA | Foreach-Object { [PSCustomObject] @{ Name = $_[0] FavColor = $_[1] } }
Now I want my real script to accept these in the input stream, and I tried all kinds of combinations of things to get the stream to bind to my input parameter.
# Process-Favorites.ps1 - INCORRECT VERSION Param( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [PSCustomObject] $Favorites ) foreach ($item in $Favorites) { Write-Output ( "{0}'s favorite color is {1}" -f $item.Name, $item.FavColor ) }
... but it only processed the last item from the input:
PS> .\create_input.ps1 | .\Process-Favorites.ps1 Bob's favorite color is Purple
Hmm. Changing the $Favorites variable to an array (as [PSCustomObject[]]) made no difference, nor did adding Position = 0 to the Parameter section. I turned a lot of knobs.
Finally I hit upon it: by changing $Favorites to the actual magic word $input, it all started working:
# Process-Favorites.ps1 - WORKING VERSION! Param( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [PSCustomObject] $input ) foreach ($item in $input) { Write-Output ( "{0}'s favorite color is {1}" -f $item.Name, $item.FavColor ) }
Poof: now it works. Does not require Position = 0, nor does the type need to be an array type.
Moral of the story: $input is a magic word in PowerShell.
Comments