A colleague of mine needed a way to have a parameter accept only a specific set of paths. I told him this can be accomplished easily with the ValidateSet decoration on the parameter, but he then explained that what the actually needed, is to have the set dynamically defined by the sub folders in the current location, instead of a pre-defined set. This sent me out on a journey to explore the dynamic parameter world.

The result of that journey, and the answer to his request is the example function below:

function Test-DynamicValidateSet {
    [CmdletBinding()]
    Param(
        # Any other parameters can go here
    )
 
    DynamicParam {
            # Set the dynamic parameters' name
            $ParameterName = 'Path'
            
            # Create the dictionary 
            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

            # Create the collection of attributes
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            
            # Create and set the parameters' attributes
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $true
            $ParameterAttribute.Position = 1

            # Add the attributes to the attributes collection
            $AttributeCollection.Add($ParameterAttribute)

            # Generate and set the ValidateSet 
            $arrSet = Get-ChildItem -Path . -Directory | Select-Object -ExpandProperty FullName
            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet)

            # Add the ValidateSet to the attributes collection
            $AttributeCollection.Add($ValidateSetAttribute)

            # Create and return the dynamic parameter
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
            return $RuntimeParameterDictionary
    }

    begin {
        # Bind the parameter to a friendly variable
        $Path = $PsBoundParameters[$ParameterName]
    }

    process {
        # Your code goes here
        dir -Path $Path
    }

}

and then you can use it:

Test-DynamicValidateSet -Path [the magic happens here]

HTH,

Martin.

Advertisements