Pipeline input into Powershell Scripts (not functions)
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.