
Dynamic parameters
All the earlier examples were examples of static parameters. Before the cmdlets of the function are executed, these parameters come into existence and remain available for the entire duration of the scope of the function. Dynamic parameters are those parameters that are defined in such a way that depending on certain conditions only, they come into existence. It may be designed in such a way that a dynamic parameter will come into existence only when another parameter is used in the function or a parameter has a certain value. So, late binding is applied for these types of parameters.
For example, let's discuss the following requirements:
- We want to create a VM, provided the VM name is given by a user.
- We have three different environments named Dedicated, Shared, and Cloud where the VM can be created.
- If any environment is not mentioned by a user, then by default the VM will be created in the shared environment.
- For a shared and Cloud environment, providing a VM name would be enough to create a VM in that environment as we will use a default user ID to create a VM in that environment.
- If a user wants to create a VM in a dedicated environment, then the script asks the user for
userid
with which the VM will be created. - In a dedicated environment, users with VM creation rights have
admin
included in theiruserid
or username. So, if the value entered by the user does not containadmin
in theiruserid
, then the task will fail.
We will use a dynamic parameter in the function to achieve the things mentioned in the preceding points. But before we go ahead and discuss the function, let's first take a look at the syntax and steps to create such a parameter:
- The syntax for the declaration is
DynamicParam {<Script block>}
. - In the script block, we will use an
If
statement block to specify the condition, which in turn will check whether the parameter will come into existence in the function or not. - In the
If
statement, we will first define the attributes of the parameter withSystem.Management.Automation.ParameterAttribute
. - Next, we need to create an attribute collection object with
System.Collections.ObjectModel.Collection[System.Attribute]
. - Then, we need to add
ParameterAttributes
to the attribute collection. - Next we need to define a runtime defined parameter object with
System.Management.Automation.RuntimeDefinedParameter
. We also need to provide the following details:- Name of the parameter
- Type of the parameter
- The attribute collection object that we created earlier
- We need to create a runtime defined parameter dictionary object with
System.Management.Automation.RuntimeDefinedParameterDictionary
. - Next, we need to add
RuntimeDefinedParameter
to theRuntimeDefinedParameterDictionary
object. - Finally, we need to return the
RuntimeDefinedParameterDictionary
object back to the runtime.
So, let's first analyze the function and, at the end, we will stitch everything together to get the final script.
First, we will define the function name. For the purpose of this function, I have declared a function with the function name, Create-VM
.
Next, CmdletBinding()
was mentioned to define that the function is an advanced function. Then, we declared two static parameters: $vmname
and $environment
, to store values of the VM name and the environment where the VM will be created, respectively. Note that the $environment
parameter can have only three values: Dedicated
, Shared
, and Cloud
. We enforced this check using the ValidateSet
attribute of the parameter.
In the next section, we defined the dynamic parameter with DynamicParam()
followed by the IF
statement, where we check whether the $environment
variable has been given a Dedicated
value or not. If it has been given this value, then the next portion will be executed and the dynamic parameter will be created. If it has not, then the next portion will not get executed and the dynamic parameter will not be created:
Function Create-VM { [CmdletBinding()] param( [Parameter( Mandatory=$true, Position=1, HelpMessage="Enter the name of the VM to be created:" )] [string]$vmname, [Parameter( Mandatory=$false, Position=2, HelpMessage="Enter the environment where you want to create the VM:" )] [ValidateSet("Dedicated","Shared","Cloud")] [string]$environment="Shared" ) DynamicParam { If ($environment -eq "Dedicated") { #declaring the parameter name for the user name $user = 'username' #creating a new ParameterAttribute Object and then setting the attributes of the parameter $userAttribute = New-Object System.Management.Automation.ParameterAttribute $userAttribute.Position = 3 $userAttribute.Mandatory = $true $userAttribute.HelpMessage = "Only named users can create a VM in this environment. Please enter your name:" #create an attributecollection object for the attributes we just created $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute] #adding our defined custom attributes to the collection $attributeCollection.Add($userAttribute) #creating the new dynamic paramater with attributes mentioned in the attribute collection $userParam = New-Object System.Management.Automation.RuntimeDefinedParameter($user, [string], $attributeCollection) #exposing the parameter to the runspace and returning it $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $paramDictionary.Add($user, $userParam) return $paramDictionary } } Begin { #Checking if the dynamic parameter was created and expected value was provided to it if ($PSBoundParameters.userName -and $PSBoundParameters.userName -NotMatch "admin") { Write-Error "You do not have enough permission to create a VM in this environment" -ErrorAction Stop } #Creating an easy parameter name for the Dynamic Parameter so that we can use it easily in the function $username = $PSBoundParameters.userName } Process { # We can create input for our custom scripts # For the purpose of checking the script we are just #printing the name to the screen here. if ($environment -ne "Dedicated") { Write-Host "You have entered VMname: $vmname Environment: $environment" } Else{ Write-Host "You have entered VMname: $vmname Environment: $environment UserID:$username " } } }
Now, let's run the function. But before we call the function and use it from the PowerShell Command Prompt, we need to import the function into our environment. To do this, we will dot source the functions in the current environment. Dot sourcing enables us to bring the variables and functions from another script into the current scope. We dot source another script in the following way:
PS C:\> . .\Create-VM.ps1
Now, we can call the function in a normal way by calling out its name:
PS C:\> Create-VM test-vm web
First, we will provide parameters that do not have values within the permissible range, that is, Dedicated
, Shared
, and Cloud
. As expected, the command fails. It shows you the reason as well.

Next, we will provide a valid value for the environment. It shows you the right information.

Now, we will provide the environment value as Dedicated
but will not provide a userid
. PowerShell will prompt us for the userid
, so we will provide a userid
that will not have an admin in the userid
. Again, as expected, the command fails saying that the user does not have enough permission. This is what we wanted.

Finally, let's provide all the correct values and see what the output is like.

Everything runs as expected.
The preceding example shows you how dynamic parameters can be used in a function to do special tasks.
These parameters are very useful, but they should be used carefully as users may find it very difficult to discover them.