One of the great things of PowerShell scripts is we can accept and validate parameters before the input values even reach our code. We can check for blank or null values or limit the input range for an argument. You can use default values and set the parameters as mandatory if needed. Almost any data type can be a parameter including strings, ints, arrays or booleans. With a boolean parameter you can explicitly set the value to either $true or $false, and the other data types have various values and ranges.

Another useful choice is the switch data type which is a variation of the boolean type. By default the value is false if you don’t include the switch argument, and true if the argument is set. One example would be the Verbose parameter which can be used with almost any built in cmdlet.

Get-ChildItem -Verbose

One limitation of the switch parameter type is that you cannot set the default value to false. Given the following script:

# BlogScripts.ps1

param(
    [switch]$AskForCredentials
)

Write-host ("AskForCredentials is {0}" -f $AskForCredentials)

The following output will be returned:

# .\BlogScripts.ps1

AskForCredentials is False

# .\BlogScripts.ps1 -AskForCredentials

AskForCredentials is True

If we default $AskForCredentials to $true in the parameter binding, the value will always be true. The below script

# BlogScriptsWithTrue.ps1

param(
    [switch]$AskForCredentials = $true
)

Write-host ("AskForCredentials is {0}" -f $AskForCredentials)

Gives this output:

# .\BlogScriptsWithTrue.ps1

AskForCredentials is True

# .\BlogScriptsWithTrue.ps1 -AskForCredentials

AskForCredentials is True

If we default $AskForCredentials to $false in the parameter binding, the default value is ignored when the switch is present. The below script

# BlogScriptsWithFalse.ps1

param(
    [switch]$AskForCredentials = $false
)

Write-host ("AskForCredentials is {0}" -f $AskForCredentials)

Gives this output:

# .\BlogScriptsWithFalse.ps1

AskForCredentials is False

# .\BlogScriptsWithFalse.ps1 -AskForCredentials

AskForCredentials is True

We cannot even override the value from the command line. If you pass in $false for the parameter value it is ignored.

# .\BlogScriptsWithFalse.ps1 -AskForCredentials $false

AskForCredentials is True

To overcome this limitation we can use the ValidateSet attribute with a string parameter and a default value to create our own switch type.

# CustomSwitch.ps1

param(
    [ValidateSet("True", "False", 0, 1)]
    [ValidateNotNullOrEmpty()]
    [string]$AskForCredentials = "False"
)

Write-host ("AskForCredentials is {0}" -f $AskForCredentials)

We can now use 0, 1, true or false as an input value for the parameter.

# .\CustomSwitch.ps1

AskForCredentials is False

# .\CustomSwitch.ps1 -AskForCredentials 1

AskForCredentials is True

# .\CustomSwitch.ps1 -AskForCredentials 0

AskForCredentials is False

# .\CustomSwitch.ps1 -AskForCredentials true

AskForCredentials is True

# .\CustomSwitch.ps1 -AskForCredentials false

AskForCredentials is False

I could have also used the boolean type instead of string for this parameter, however we cannot then convert the string values true or false as part of the parameter passing. If you try you will get an error like below:

Cannot process argument transformation on parameter 'AskForCredentials'. Cannot convert value "System.String" to type "System.Boolean".
Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or 0.

Therefore the values of $true or $false will have to be used and in my opinion this is not ideal. If your parameters are being generated by an external system or as part of the output of another script, having to remember to prepend the $ to the value to be passed makes the script harder to use.

Now that the parameter is in your script, we now need to correct the data type to a boolean. This is done using the helper function ConvertStringToBoolean as shown below:

# CustomSwitch.ps1 -$AskForCredentials true

function ConvertStringToBoolean ([string]$value) {
    $value = $value.ToLower();

    switch ($value) {
        "true" { return $true; }
        "1" { return $true; }
        "false" { return $false; }
        "0" { return $false; }
    }
}

[bool]$AskForCreds = ConvertStringToBoolean($AskForCredentials);

This helper function could be extended to also cater for $true or $falseif needed. The variable $AskForCreds can now used as normal in your script.

At the end of the day, this code has helped me solve a problem I encountered. In doing so I have covered various points related to parameter handling in PowerShell scripts, so hopefully you have learned something useful too.