I am building a function. At times, I want to be able to provide parameter inputs for the function via the pipeline, because often the values are found on a csv file:
$CsvData = @"
Label,Key, IsSubTrigger
Function10,f10, 0
Function11,f11, 1
Function12,f12, true
Function13,f13, false
"@ |ConvertFrom-Csv
The following is the bare bones function:
Function foo{
[CmdletBinding()]
Param(
[parameter(ValueFromPipelineByPropertyName)]
[string]$Label,
[parameter(valuefrompipelinebypropertyname)]
[string]$key,
[parameter(valuefrompipelinebypropertyname)]
[switch]$IsSubTrigger,
[parameter(ValueFromPipeline)]
[string]$Path
)
Process{
"Label:" + $Label,
"key: " + $Key,
"IsSubTrigger: " + $IsSubTrigger
}
}
Invoking $CsvData | foo
outputs an error for each csv row:
foo: Cannot process argument transformation on parameter 'IsSubTrigger'. Cannot convert value "System.String" to type "System.Management.Automation.SwitchParameter". Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or 0.
I have tried solving this but but have sadly gotten nowhere.
PowerShell doesn't know how to properly coerce a string
into a SwitchParameter
, which leads to the issue you're observing:
[switch] 'true'
# InvalidArgument: Cannot convert the "true" value of type "System.String" to type "System.Management.Automation.SwitchParameter".
What you can do to help it, is create an argument transformation class, essentially a class that inherits from ArgumentTransformationAttribute
, that handles the logic for converting a string
into a bool
, then that bool
can be coerced into SwitchParameter
without issues later on:
class BoolParseTransformation : System.Management.Automation.ArgumentTransformationAttribute {
[Object] Transform([System.Management.Automation.EngineIntrinsics] $engineIntrinsics, [Object] $inputData) {
$int = 0
if ([int]::TryParse($inputData, [ref] $int)) {
return [bool] $int
}
return [bool]::Parse($inputData)
}
}
Then in your param
block, you can implement it like this:
function foo {
[CmdletBinding()]
param(
[Parameter(ValueFromPipelineByPropertyName)]
[string] $Label,
[Parameter(ValueFromPipelineByPropertyName)]
[string] $key,
[Parameter(ValueFromPipelineByPropertyName)]
[BoolParseTransformation()]
[switch] $IsSubTrigger,
[Parameter(ValueFromPipeline)]
[string] $Path
)
process { $PSBoundParameters }
}