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 $false
if 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.