Author Posts

November 13, 2017 at 12:56 pm

Hi ,

got into a problem with DynamicParams,

    an example code
function test{
    [Cmdletbinding()]
    Param(
        [Parameter(Mandatory)]
        $r
    )

DynamicParam {
    if( $r -eq 'Yes' ){

        $ParameterDictionary        = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary
        $ParamAttribute             = New-Object -TypeName System.Management.Automation.ParameterAttribute
        $ParamAttribute.Mandatory   = $True
        $AttributeCollection        = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]
        $AttributeCollection.Add( $ParamAttribute )        
        $Param                      = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter('t', [String], $AttributeCollection)    
        $ParameterDictionary.Add('t',$Param) | out-null
    return $ParameterDictionary

    }

}
Process{
    $PSBoundParameters
}

}

when I execute by mentioning -r and with the expected 'yes' value, Parameter 'r' is having the value in it in DynamicParam{} and if loop passes.

test -r 'yes'

when I execute without mentioning -r and giving the expected value 'yes' when prompted as its mandatory, Parameter 'r' is not having the value in it in DynamicParam{} and if loop fails.

test

I can see key 'r' in the $PSBoundParameters, but the value is empty,

any idea ?

November 13, 2017 at 1:27 pm

I typically won't define 'r' in the Param() section uptop, I would only define it in the DynamicParam {} script block as in:

function test-Dynamic1 {
    [CmdletBinding(ConfirmImpact='Low')]Param()

    DynamicParam  {
        $ParamAttrib = New-Object System.Management.Automation.ParameterAttribute
        $ParamAttrib.Mandatory  = $true
        $ParamAttrib.ParameterSetName  = '__AllParameterSets'  
        $RuntimeParamDic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

        #region Add r dynamic variable - Only change the next 2 lines for each additional dynamic parameter you add
        $varName = 'r'
        $varValues = (Get-ChildItem .\).FullName
        $AttribColl = New-Object  System.Collections.ObjectModel.Collection[System.Attribute]
        $AttribColl.Add($ParamAttrib)
        $AttribColl.Add((New-Object  System.Management.Automation.ValidateSetAttribute($varValues)))  
        $RuntimeParam  = New-Object System.Management.Automation.RuntimeDefinedParameter($varName, [string],$AttribColl)
        $RuntimeParamDic.Add($varName, $RuntimeParam)
        #endregion

        $RuntimeParamDic  
    }

    Process{
        "r: ($($PSBoundParameters.r))"
    }
}

Line 6 $ParamAttrib.Mandatory = $true is where you make 'r' mandatory.
To add additional dynamic parameters you repeat the #region inside the DynamicParam{} script block. You typically would populate the $varName and $varValues only.
Finally you don't refer to $r in the script, but instead you refer to $PSBoundParameters.r

November 13, 2017 at 4:34 pm

You didn't get the problem here, I can make as much as DynamicParam I want, Problem is in accessing the variables declared in Param block inside the dynamicparam block if the variable in Praam block is not provided while calling the Function/Script, But asked for the value as it is defined as mandatory.

This is same in case if I have 2 dynamicParams and accessing 1st param's value to take a decision within the DynamicParam block.

November 14, 2017 at 12:08 am

Running your code snippet unchanged, and just let it prompt me, I get the below, so, unless I am missing the point. I am not getting empty value returns:

test
cmdlet test at command pipeline position 1
Supply values for the following parameters:
r: yes

Key Value
— —–
r yes

When I use your code as you do, I get

test -r 'yes'
cmdlet test at command pipeline position 1
Supply values for the following parameters:
t:

test -r 'yes'
cmdlet test at command pipeline position 1
Supply values for the following parameters:
t: yes

Key Value
— —–
r yes
t yes

Doing the same thing quoting the string, I get

test
cmdlet test at command pipeline position 1
Supply values for the following parameters:
r: 'yes'

Key Value
— —–
r 'yes'

Removing the quotes from the string as you have it, I get

test -r yes
cmdlet test at command pipeline position 1
Supply values for the following parameters:
t:

test -r yes
cmdlet test at command pipeline position 1
Supply values for the following parameters:
t: $r

cmdlet test at command pipeline position 1
Supply values for the following parameters:
t: $r

Key Value
— —–
r yes
t $r

November 14, 2017 at 2:06 am

Your line 16 reads

        $Param                      = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter('t', [String], $AttributeCollection)    

It is looking for a parameter called "t" as per what am seeing. This is what I got, confusing to me:

PS C:\windows\system32> test -r yes
cmdlet test at command pipeline position 1
Supply values for the following parameters:
t:
test : Cannot bind argument to parameter 't' because it is an empty string.
At line:1 char:1
+ test -r yes
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [test], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,test

PS C:\windows\system32>

November 14, 2017 at 6:38 am

Hi Pradeep, what I have posted is a pseudo code.

The actual problem here is the value of a Parameter (here it is 'r') from the Param() block is not bound or visible in the DynamicParam block.

My question is , is it by design or Am I missing something else ?

November 14, 2017 at 4:08 pm

I have posted it in UserVoice.

Vote if you feel it as a deficiency .