Monthly Archives: May 2013

PowerShell: Simple way to add dynamic parameters to advanced function


I’ve been working on a module for Nimble Storage and I’ve been creating dynamic parameters for some of the functions and I thought, why not just create a helper function for this? So I did, here it is with a simple example. The code is actually not too bad once you look through it, mostly just populating some objects and dumping them in the DynamicParam block.

Thanks Bart for the initial help! :)

Two important notes about this:
1) You have to supply Begin/Process/End (dont need all, but need at least 1)
2) It does not populate the variable as you’d expect it to, you have to pull it from $PSBoundParameters

Function New-DynamicParam {
param(
[string]
$Name,
[string[]]
$Options,
[switch]
$mandatory,
[string]
$SetName="__AllParameterSets",
[int]
$Position,
[switch]
$ValueFromPipelineByPropertyName,
[string]
$HelpMessage

)
    #param attributes   
    $ParamAttr = New-Object System.Management.Automation.ParameterAttribute
    $ParamAttr.ParameterSetName = $SetName
    if($mandatory){ $ParamAttr.Mandatory = $True }
    if($Position -ne $null){$ParamAttr.Position=$Position}
    if($ValueFromPipelineByPropertyName){$ParamAttr.ValueFromPipelineByPropertyName = $True}
    if($HelpMessage){$ParamAttr.HelpMessage = $HelpMessage}

    ##param validation set
    $ParamOptions = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList $options

    $AttributeCollection = New-Object 'Collections.ObjectModel.Collection[System.Attribute]' 
    $AttributeCollection.Add($ParamAttr)
    $AttributeCollection.Add($ParamOptions)

    $Parameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter `
    -ArgumentList @($Name, [string], $AttributeCollection)
            
    $Dictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
    $Dictionary.Add($Name, $Parameter)
    $Dictionary
}

Here is an example of how you would use it.

function Show-Free
{
    [CmdletBinding()]
    Param()
    DynamicParam {
    New-DynamicParam -name Drive -options @(gwmi win32_volume |%{$_.driveletter}|sort) -Position 0 
    }
    begin{
    #have to manually populate
    $drive = $PSBoundParameters.drive
    }
    process{
    $vol = gwmi win32_volume -Filter "driveletter='$drive'"
    "{0:N2}% free on {1}" -f ($vol.Capacity / $vol.FreeSpace),$drive
    }
}

I’ve set this up to only work with strings, but if you look at the code there is actually nothing forcing you to use strings, just makes most sense for this.

Enjoy!

Advertisements