PowerShell ValidateSet on Boolean Parameter

8.7k Views Asked by At

I am attempting to use ValidateSet with a boolean parameter however I cannot get it to function as expect.

An example to replicate the issue:

function Set-Boolean
{
    [CmdletBinding()]
    [OutputType([Bool])]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet($false,$true)]
        [Bool] $Bool
    )

    Process
    {
        $Bool
    }
}

At run time PowerShell expands the $true and $false variables upon tab completion to True and False respectively however this then cause the parameter validation to fail as only $true, $false, 1 and 0 are valid boolean types.

I tried changing ValidateSet to [ValidateSet('$false','$true')] and the tab completion works as expected however the parameter validation still fails as the parameter is expecting the strings '$false' and '$true'.

I could change ValidateSet to [ValidateSet([bool]0,[bool]1)] and have it function as I expect but I find 0 and 1 a poorer user experience over $true and $false for completion of a boolean parameter.

The expected output of the function should be True when $true is chosen and False when $false is chosen.

I have implemented a workaround in my code but I want to know how I can use ValidateSet with a boolean parameter, if it is possible, to enable the use of tab completion for the user.

3

There are 3 best solutions below

2
On BEST ANSWER

You can use ValidateSet for autocompletion without specifying the input variable type. Though, you cannot use 0 and 1 as input in this case:

function Set-Boolean
{
    [CmdletBinding()]
    [OutputType([Bool])]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet($false,$true)]
        $Bool
    )

    Process
    {
        [System.Convert]::ToBoolean($Bool)
    }
}
0
On

Joining some answers, the best option will depend on the needs, if the parameter is type boolean it can be replaced by one of type switch, but if you want to specify the value to see in the code or by style; It can be done as follows.

function Write-SwitchParam {
    [CmdletBinding()]
    param (
        [Switch] #[Switch] or [System.Management.Automation.SwitchParameter]
        $SwitchParam
    )

    if($SwitchParam)
    {
        Write-Host "Switch is present. Do Positive Action."
    }
    else {
        Write-Host "Switch isn't present. Do Negative Action."
    }
}

function Write-BooleanParam {
    [CmdletBinding()]
    Param(
    [parameter(Position=0, ValueFromPipeline=$true)]
    [ValidateNotNullOrEmpty()]
    [ValidateSet($true, $false, 0, 1)]
    $BoolParam = $true
    )

    Begin{  
    }

    Process{
        $value = [System.Convert]::ToBoolean($BoolParam)
        Write-Host $value
    }

    End{
    }   
}

Write-Host "TESTS BOOLEAN PARAM" -ForegroundColor Magenta
Write-BooleanParam -BoolParam $true
Write-BooleanParam -BoolParam $false
Write-Host

Write-BooleanParam $false
Write-BooleanParam $true
Write-Host

Write-BooleanParam True
Write-BooleanParam False
Write-Host

Write-BooleanParam 0
Write-BooleanParam 1
Write-Host

Write-BooleanParam
Write-Host

$true, $false, "True", "False", 1, 0 | Write-BooleanParam
Write-Host

Write-Host "TESTS SWITCH PARAM" -ForegroundColor Magenta
Write-SwitchParam 
Write-SwitchParam -SwitchParam

Console Output

1
On

This gives the tab completion for the user, as desired using ValidateSet, but is achieved by registering an argument completer instead (especially in the ISE);

function Set-Boolean
{
    [CmdletBinding()]
    [OutputType([Bool])]
    Param
    (
        [Parameter(Mandatory=$true, Position=0)]
        [ValidateNotNullOrEmpty()]
        [Bool] $Bool
    )

    Process
    {
        $Bool
    }
}
Register-ArgumentCompleter -CommandName 'Set-Boolean' -ParameterName 'Bool' -ScriptBlock {
    [System.Management.Automation.CompletionResult]::new(
        '$False',
        '$False',
        'ParameterValue',
        '[bool] False'
    )
    [System.Management.Automation.CompletionResult]::new(
        '$True',
        '$True',
        'ParameterValue',
        '[bool] True'
    )
}