5

Trying to get a better understanding of Dynamic Parameters, but something keeps bothering me. All examples I've found across the outer-webs (internet), the parameter attributes are always defined/included.

Here's what I'm working with:

Function Test-DynamicParameters {
[cmdletbinding()]
    Param (
        [System.IO.DirectoryInfo]$Path
    )
    DynamicParam
    {
        if ($Path.Extension) {
              $parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
                  Mandatory = $false
              }

              $attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
              $attributeCollection.Add($parameterAttribute)

              $dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
                'TestSwitch', [switch], $attributeCollection
              )

              $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
              $paramDictionary.Add('TestSwitch', $dynParam1)
              $paramDictionary
        }
    }
    Begin { }
    Process
    {
        $PSBoundParameters
    }
    End { }
}

. . .currently have tried numerous combinations of removing certain lines/code to see what would make my Dynamic Parameter show, but nothing works without the attributes being declared. Is this necessary?

Question: what is the simplest form of Dynamic Parameter declaration that I would need for it to work?

For Example - can it just be shortened to where I only define just the name? Or, would PowerShell insist a type is specified instead of defaulting to [object]? Something like:

$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('TestSwitch')
$paramDictionary

2 Answers 2

3

What kind of behavior are you looking for? Because dynamic parameters are usually not needed, even if the auto-completion is dynamic.

For example you could do

  • autocomplete module names for Get-Command -Module
  • or search for files by filetype, only complete filetypes if they exist in that directory

Windows Powershell

You can use DynamicValidateSet pattern in WindowsPowershell

gif using DynamicValidateSet

https://i.sstatic.net/nnLBS.gif

New in PowerShell

6 adds Suggestions

New: [IValidateSetValuesGenerator] and [ArgumentCompletions]

It autocompletes like [ValidateSet], but the user is still free to enter others.

Note, [ArgumentCompletions] and [ArgumentCompleter] are two different classes.

[Parameter(Mandatory)]
[ArgumentCompletions('Fruits', 'Vegetables')]
[string]$Type,

7.2 Generic Completers

New [ArgumentCompleter] attribute with the [IArgumentCompleterFactory] interface

from the docs:

[DirectoryCompleter(ContainingFile="pswh.exe", Depth=2)]

[DateCompleter(WeekDay='Monday', From="LastYear")]

[GitCommits(Branch='release')]
1
  • Very neat stuff, wasn't aware of such a feature; PowerShell is just so cool. Unfortunately, what I'm looking for is certain parameters (not values) to become available based on certain conditions from other parameters. In this case though, I'm just looking to see what it takes to initialize a dynamic parameter with the least amount of code. I.e. what classes do I need to instantiate so my parameter becomes available at runtime. Hopefully this makes some sense. Commented Dec 30, 2021 at 16:55
1

You can’t as the function add of the type System.Management.Automation.RuntimeDefinedParameterDictionary require to provide a key and value which is exactly a String (key) and a System::Management::Automation::RuntimeDefinedParameter for the value. For more information you can check the class documentation here https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runtimedefinedparameterdictionary?view=powershellsdk-7.0.0.

I have tested on my side and you need at least the ParameterAttribute Mandatory set to true in order to make it run, and the key/name used in the RuntimeDefinedParameter must match the key used in the dictionary when you add it.

So the minimum code that you need should be like this:

Function Test-DynamicParameters {
[cmdletbinding()]
    Param (
        [System.IO.FileSystemInfo ]$Path
    )
    DynamicParam
    {
        if ($Path.Extension) {
              $parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
               Mandatory = $true
              }

              $attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
              $attributeCollection.Add($parameterAttribute)

              $dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new("TestSwitch", [string], $attributeCollection)

              $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
              $paramDictionary.Add('TestSwitch', $dynParam1)
              $paramDictionary
        }
    }
    Begin { }
    Process
    {
        $PSBoundParameters
    }
    End { }
}
$FileNamePath = "C:\tmp\stackoverflow\test.txt";
$path = (Get-Item $FileNamePath )
Test-DynamicParameters -Path $path
1
  • 1
    Hello! My current code works without the need to set the mandatory property to $true, but I think you may be right as far as this being the least amount of code need to initialize a Dynamic Parameter. I think the objects instantiated are dependent on one another. Commented Dec 30, 2021 at 17:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.