functionpowershellparameter-sets

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?


Solution

  • 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.