Building Dynamic Parameters and Powershell Parameter Validation

Adam Bertram

Read more posts by this author.

One of the coolest yet complex features of advanced functions in PowerShell is dynamic parameters and using that feature to perform PowerShell parameter validation. Dynamic parameters take your typical function parameters to a whole new level.

Have you ever had a time when you created an advanced function and wanted your parameters to depend on something else; to dynamically be created based on the criteria you choose at runtime?

How about wanting Powershell parameter validation like building a PowerShell ValidateSet array providing tab-completion on a parameter not based on a static set of stings but generated at runtime? These are both doable with dynamic parameters.

This post is part of the PowerShell Blogging Week (#PSBlogWeek) series on Windows PowerShell Advanced Functions, a series of coordinated posts designed to provide a comprehensive view of a particular topic.

In this series, we also have:

To suggest a PowerShell Blogging Week topic, leave a comment or tweet it to us with the #PSBlogWeek hashtag.

There are a couple of different ways to use dynamic parameters that I’ve seen. The first is the way that Ben Ten wrote about them on PowerShell Magazine. Using this method, Ben was able to create parameters on the fly based on if a different parameter was used. Personally, I’ve never had a need to do this.

I really like using dynamic parameters as a way to validate input based on some criteria that are available at runtime. This way I can write a script that gathers information on-the-fly which allows me the beautiful parameter tab-completion we all know and love.

Let’s go over an example on how to create Powershell parameter validation based on files in a folder.

“Normal” advanced function parameters allow you to use a few Validate options. You can validate the number of arguments a parameter can accept, the minimum and maximum length of a parameter argument, a set of options in an array, matching a regex string or a scriptblock and more. What I’m looking for here is to use the ValidateSet attribute for the tab-completion.

Tab completion in PowerShell
Tab completion in PowerShell

You’ll notice in the example above I’m using the Get-Item cmdlet and the default parameters for tab-completion which is to be expected. I want that functionality but I want to tab-complete my own arguments so let’s create a simple function to do that.

The PowerShell ValidateSet parameter validation attribute
The PowerShell ValidateSet parameter validation attribute

You’ll notice that I’ve highlighted the validation attribute that will allow us to tab-complete the MyParameter argument. Now we’re able to get custom parameter argument tab-completion using the values specified in the PowerShell ValidateSet array attribute.

Tab-completion with dynamic parameters
Tab-completion with dynamic parameters

But now what if I want my tab-completion options to be generated on-the-fly based on some other criteria rather than a static list? The only option is to use dynamic parameters. In my example, I want to tab-complete a list of files in a particular folder at run-time.

To get this done I’ll be using a dynamic parameter which will run Get-ChildItem whenever I try to tab-complete the MyParameter parameter.

With that being said, let’s make the ValidateSet attribute of the MyParameter parameter dynamic, shall we?

The first difference between a standard parameter and a dynamic parameter that you’ll notice is dynamic parameter are in their own block.

DynamicParam {


Creating a Dynamic Powershell Validation Parameter the Hard Way

Inside the DynamicParam block is where the magic happens. And the magic does take a while to wrap your head around.

A dynamic parameter is, in a sense, a System.Management.Automation.RuntimeDefinedParameterDictionary object with one or more System.Management.Automation.RuntimeDefinedParameter objects inside of it. But it’s not quite that easy. Let’s break it down.

  1. First, instantiate a new System.Management.Automation.RuntimeDefinedParameterDictionary object to use as a container for the one or more parameters we’ll be adding to it using
$RuntimeParamDic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary.

2. Next, create the System.Collections.ObjectModel.Collection prepped to contain System.Attribute objects.

$AttribColl = New-Object System.Collections.ObjectModel.Collection[System.Attribute].

3. Now instantiate a System.Management.Automation.ParameterAttribute object which will hold all of the parameter attributes we’re used to. In our instance, I’m defining my parameter to be in all the parameter sets and accept pipeline input by a pipeline object and by property name.

$ParamAttrib = New-Object System.Management.Automation.ParameterAttribute
$ParamAttrib.Mandatory = $Mandatory.IsPresent
$ParamAttrib.ParameterSetName = '__AllParameterSets'
$ParamAttrib.ValueFromPipeline = $ValueFromPipeline.IsPresent
$ParamAttrib.ValueFromPipelineByPropertyName = $ValueFromPipelineByPropertyName.IsPresent

4. Add our parameter attribute set to the collection we instantiated above.


5. Because I’m using this dynamic parameter to build a PowerShell ValidateSet array for parameter validation I must also include a System.Management.Automation.ValidateSetAttribute object inside of our attribute collection. This is where you define the code to actually create the values that allows us to tab-complete the parameter arguments.

$AttribColl.Add((New-Object System.Management.Automation.ValidateSetAttribute((Get-ChildItem C:\TheAwesome -File | Select-Object -ExpandProperty Name))))

6. We then have to instantiate a System.Management.Automation.RuntimeDefinedParameter object using the parameter name, it’s type and the attribute collection we’ve been adding stuff to.

$RuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter('MyParameter', [string], $AttribColl)

7. Once the run time parameter is finished we then come back to that original dictionary object we instantiated earlier using the parameter name and the runtime parameter object we created.

$RuntimeParamDic.Add('MyParameter', $RuntimeParam)

8. We can then return this runtime dictionary object back to the dynamic parameter block and we’re done!

return $RuntimeDic

Are your eyes glazing over yet? Mine was when I first tried to figure this out.

Being the lazy admin I am I created a function called New-ValidationDynamicParam that does all this work for you creating the PowerShell ValidateSet array. Simply pass in the parameter name, the attributes you’d like the parameter to have and the code you’ll be using to create the validation and you’re done! The function does the rest.

Creating a Dynamic ValidateSet Array Parameter the Easy Way

New-ValidationDynamicParam -Name 'MyParameter' -Mandatory -ValidateSetOptions (Get-ChildItem C:\TheAwesome -File | Select-Object -ExpandProperty Name)

My pain is your gain, people!

Now, with our dynamic validation parameter created, let’s take it for test drive.

I’ve got some files in a directory on my computer that I only want to be passed to the MyParameterparameter.

Sample text files
Sample text files

Now all I have to do is run our script and voila! I’m now only able to use the file names as parameter arguments and they are updated as the files comes in and out of the folder!

Using the dynamic parameter creation script
Using the dynamic parameter creation script

Subscribe to Stay in Touch

Never miss out on your favorite ATA posts and our latest announcements!

Looks like you're offline!