powershellparameters

Issues with Parameter sets in a function not working as expected


This is a barebones version of a function I am working on:

function Get-Firefox{
    [CmdletBinding(DefaultParameterSetName = 'Global')]
    Param(
    [Parameter(ParameterSetName="Global")]
    [ArgumentCompletions('Title', 'Url', 'SingleLine', 'MultiLine')]
    [String]$ActiveTab,
    
    [Parameter(ParameterSetName="Global")]
    [Switch]$ActiveVideo,
    
    [Parameter(ParameterSetName="Global")]
    [ArgumentCompletions('Title', 'Url')]
    [String]$AllTabs,

    [Parameter(ParameterSetName="History")]
    [String]$History,
    
    #These should only be available when parameter "-History" is present
    [Parameter(ParameterSetName="History")]
    [Switch]$Title,
    [Parameter(ParameterSetName="History")]
    [Switch]$URL,
    [Parameter(ParameterSetName="History")]
    [Switch]$SingleLine,
    [Parameter(ParameterSetName="History")]
    [Switch]$MultiLine)
    

        Begin{
        }
        process {
            Switch ($PSBoundParameters.Keys){
                'ActiveTab'{ 

                }
                'AllTabs'{
    
                }
                'History'{
                    
                    $PSCmdlet.ParameterSetName
                }
                }
            }
         
 }

I am struggling with integrating parameter sets into it. I dont know if this is the behaviour to be expected or not.

The behaviour I am expecting is: if parameter -History is not present then parameters

SHOULD not be avaible for use.

Yet if I type Get-Firefox and then press <Tab> the paramters belonging to ParameterSetName="History" are suggested by Powershell.

I thought maybe this is just a case of Powershell not being smart enough to hide these parameters from autcompletion.

Yet I can also use the history parameter with any other parameters like, Get-Firefox -ActiveTab -SingleLine.

Is my code wrong or have I missunderstood this and my expected behaviour is not possible?

Any help would be really wellcome


Solution

  • You can use Dynamic Parameters to define at runtime these parameters that should be only available if -History is used. In this example I'm using a loop to instantiate all the RuntimeDefinedParameter because they're all of the same type ([switch]) and their parameter declaration is just belonging to the ParameterSetName = 'History' however the recommendation would be to define each one of them manually instead of using a loop.

    function Get-Firefox {
        [CmdletBinding(DefaultParameterSetName = 'Global')]
        param(
            [Parameter(ParameterSetName = 'Global')]
            [ArgumentCompletions('Title', 'Url', 'SingleLine', 'MultiLine')]
            [String] $ActiveTab,
    
            [Parameter(ParameterSetName = 'Global')]
            [Switch] $ActiveVideo,
    
            [Parameter(ParameterSetName = 'Global')]
            [ArgumentCompletions('Title', 'Url')]
            [String] $AllTabs,
    
            [Parameter(ParameterSetName = 'History')]
            [String] $History
        )
    
        dynamicparam {
            if ($PSCmdlet.ParameterSetName -ne 'History') {
                return
            }
    
            $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
            foreach ($param in 'Title', 'URL', 'SingleLine', 'MultiLine') {
                $paramDictionary[$param] = [System.Management.Automation.RuntimeDefinedParameter]::new(
                    $param, [switch], @([Parameter]@{ ParameterSetName = 'History' }))
            }
            $paramDictionary
        }
    }