I'm trying to duplicate a typical powershell -Computername parameter that's available from the pipeline and as a normal parameter using CmdletBinding
and ValueFromPipeline
. My challenge is that I'm getting different results from specifying the parameter versus piping in values.
My code looks like this:
[CmdletBinding()]
param(
[parameter(Mandatory=$true, ValueFromPipeline=$true)] [string[]]$ComputerName
)
BEGIN { "Begin script`n-----" }
PROCESS {
" `$ComputerName '$ComputerName'"
" `$_ '$_'"
" +++ Count: " + $ComputerName.Count
foreach($computer in $ComputerName) {
" `$computer '$computer'"
}
" -----"
}
END { "Complete" }
When I run this using a pipeline, I get this:
PS> (1, 2, 3) | .\BPEParamTest.ps1 Begin script ----- $ComputerName '1' $_ '1' +++ Count: 1 $computer '1' ----- $ComputerName '2' $_ '2' +++ Count: 1 $computer '2' ----- $ComputerName '3' $_ '3' +++ Count: 1 $computer '3' ----- Complete
However, when run with a parameter, I get different results:
PS> .\BPEParamTest.ps1 -ComputerName (1, 2, 3) Begin script ----- $ComputerName '1 2 3' $_ '' +++ Count: 3 $computer '1' $computer '2' $computer '3' ----- Complete
I always use the following construction. This works for arrays in a parameter as well as from the pipeline:
[CmdletBinding()]
param(
[parameter(Mandatory=$true, ValueFromPipeline=$true)] [string[]]$ComputerName
)
process {
foreach($computer in $computername){
#do the stuff
}
Full explanation: The process block is run once for each item in the pipeline, so that's how it handles lists on the pipeline (i.e. $computername is set to each item in turn). If you pass the values as a parameter, the $computername is set to the list which is why there's a loop.