Daniel Daniel - 3 months ago 16
PowerShell Question

Parameter sets - how do I make the default work?

I'm writing a function that updates a *.CSV file to be picked-up by a puppet script that will update a DNS Zone. Since I don't want to break the real .CSV file, I've added a dummy-file. While I'm developing this function, I have three parameter sets:

Reset
,
Add
, and
Remove
. These parameters will overwrite my dummy file with the current canonical .CSV file, add a record, and delete a record, respectively. The main script will never call the function with two or all three of these switches active.

Here's how I've coded my script's parameter block:

function Update-DNS_Dev
{
[CmdletBinding(defaultparametersetname='Reset')]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0,
ParameterSetName='Reset')]
[switch]$Reset,

[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0,
ParameterSetName='Remove')]
[switch]$Remove,

[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0,
ParameterSetName='Add')]
[switch]$Add,

# Name of a Dummy file
[Parameter(ValueFromPipelineByPropertyName=$true,
Position=1)]
[string]$DummyFile = "{0}\dPvmnames.csv" -f $DNSScratchpad,

[Parameter(ValueFromPipelineByPropertyName=$true,
ParameterSetName='Remove')]
[Parameter(ValueFromPipelineByPropertyName=$true,
ParameterSetName='Add')]
[string]$servername,

[Parameter(ValueFromPipelineByPropertyName=$true,
ParameterSetName='Add')]
[Parameter(ValueFromPipelineByPropertyName=$true,
ParameterSetName='Remove')]
[string]$domain,

[Parameter(ValueFromPipelineByPropertyName=$true,
ParameterSetName='Add')]
[string]$details,

[Parameter(ValueFromPipelineByPropertyName=$true,
ParameterSetName='Add')]
[string]$type
)
}


Lower in the script, I use
switch ($psCmdlet.ParameterSetName)
to process the switches' various functionalities. When I do a
Get-Help Update-DNS
, I see expected output:

PS> get-help Update-DNS_Dev

NAME
Update-DNS_Dev

SYNTAX
Update-DNS_Dev [-Reset] [[-DummyFile] <string>] [<CommonParameters>]

Update-DNS_Dev [-Remove] [[-DummyFile] <string>] [-servername <string>] [-domain <string>] [<CommonParameters>]

Update-DNS_Dev [-Add] [[-DummyFile] <string>] [-servername <string>] [-domain <string>] [-details <string>] [-type <string>] [<CommonParameters>]


When I invoke the function and supply the
-Reset
parameter, my script executes as expected, but if I invoke it without any parameters, my default does not take effect, and hitting
1
,
$true
,
true
, or the Enter key to accept what appears to be the default
-Reset
parameter always throws a red error message:

PS> Update-DNS_Dev 
cmdlet Update-DNS_Dev at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
Reset:

Update-DNS_Dev : Cannot process argument transformation on parameter 'Reset'.
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.
At line:1 char:1
+ Update-DNS_Dev
+ ~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Update-DNS_Dev], ParameterBindingArgumentTransformationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Update-DNS_Dev


Does anyone have a suggestion of how I can get my function to take the
-Reset
switch default if the code calling the function does not supply any parameters?

Answer

While I would normally encourage [Switch] parameters to be mandatory when they define a parameter set, in your case you can't have it that way, and as PetSerAl said you must make it optional.

The reason comes down to what Mandatory actually means. It doesn't mean only that it must have a value, it means that the parameter must be bound as in, supplied by the caller. This is the same reason why giving a default value to a mandatory parameter doesn't work.

Comments