I have the following snippet of a functions parameters and their sets
function Test {
[CmdletBinding(DefaultParameterSetName='StringConsole')]
param (
[Parameter(Mandatory,
ValueFromPipelineByPropertyName,
ParameterSetName = 'ObjectFile')]
[Parameter(Mandatory,
ValueFromPipelineByPropertyName,
ParameterSetName = 'StringFile')]
[Alias("PSPath")]
[ValidateNotNullOrEmpty()]
[string]
$Path,
[Parameter(Mandatory,
ValueFromPipeline,
ParameterSetName='StringFile',
Position = 0)]
[Parameter(Mandatory,
ValueFromPipeline,
ParameterSetName='StringConsole',
Position = 0)]
[ValidateNotNullOrEmpty()]
[string]
$Message,
[Parameter(Mandatory,
ValueFromPipeline,
ParameterSetName='ObjectFile',
Position = 0)]
[Parameter(Mandatory,
ValueFromPipeline,
ParameterSetName='ObjectConsole',
Position = 0)]
[ValidateNotNullOrEmpty()]
[object]
$Object,
[Parameter(ParameterSetName='StringFile')]
[Parameter(ParameterSetName='StringConsole')]
[ValidateSet('Information', 'Verbose', 'Warning', 'Error', 'Object')]
[string]
$Severity = 'Information',
[Parameter(ParameterSetName='StringFile')]
[Parameter(ParameterSetName='StringConsole')]
[switch]
$NoPreamble,
[Parameter(ParameterSetName = 'StringConsole')]
[Parameter(ParameterSetName = 'ObjectConsole')]
[switch]
$Console
)
}
If I call the function using
Test 'Hello, World'
it properly uses the StringConsole
default parameter set from CmdletBinding
If I call the function using
Test -Message 'Hello, World' -Path C:\SomeFile.txt
It properly uses the StringFile
parameter set
But if I call the function using
Test 'Hello, World' -Path C:\SomeFile.txt
I get this error and the function doesn't execute:
Parameter set cannot be resolved using the specified named parameters
The error specifically states it couldn't resolve the parameter set using the NAMED parameters. If a parameter gets bound by position does it not also satisfy the "named" parameter? Or do you have to specifically bind the parameter using the name?
Is there anyway I could design the parameter sets to make my last example work and not throw an error?
The logic used for your parameter sets looks perfectly fine but the issue is that you have 2 parameters with Position = 0
(-Message
and -Object
), normally this wouldn't be a problem but one of them is of the type System.Object
and since all objects inherit from this class, no matter what you pass as argument in position 0 it will match this parameter. Since the other parameter on Position = 0
is of type System.String
then 'Hello, World'
(a string but also an object) matches both parameter sets and the binder has no idea which one did you mean to use.
A very easy way of seeing this, without changing your current code and just adding $PSCmdlet.ParameterSetName
to the function's body, would be to pass an integer as positional parameter and everything works as expected:
function Test {
[CmdletBinding(DefaultParameterSetName='StringConsole')]
param(
# same param block here
)
'Using: ' + $PSCmdlet.ParameterSetName
}
Test 0 -Path C:\SomeFile.txt # => Using: ObjectFile