locked
Use the value from other dynamic parameter RRS feed

  • Question

  • I want to use the value I choose from $Collection parameter for $Project parameter. For now i've hard coded it as "DefaultCollection" 

    Function TEST
    {
           DynamicParam
        {
            if ($Environment -eq "Prod")
            {
                $tfsUri = "http://tfsProd"
            }
            else
            {
                $tfsUri = "http://tfsTest"
            }

            # Set the dyanmic param name
            $ParameterName = 'Collection'

            # Create the dictionary
            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

            # Create the collection of attributes
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]

            # Create and set the parameter's attributes
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute  
            $ParameterAttribute.Mandatory = $true
            $ParameterAttribute.Position = 2

            # Add the attributes to the attributes collection
            $AttributeCollection.Add($ParameterAttribute)

            # Generate and set the ValidateSet
            $urlCollection = "$tfsUri/_apis/projectcollections?api-version=1.0"
            $projectCollections = @(Invoke-RestMethod -UseDefaultCredentials -Method Get -uri $urlCollection).value.name
            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($projectCollections) 

            # Add the ValidateSet to the attributes collection
            $AttributeCollection.Add($ValidateSetAttribute)

            # Create and return the dynamic parameter
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)

            ############
            # Set the dyanmic param name
            $ParameterName_a = 'Project'

            # Create the dictionary
            #$RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

            # Create the collection of attributes
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]

            # Create and set the parameter's attributes
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute  
            $ParameterAttribute.Mandatory = $true
            $ParameterAttribute.Position = 3

            # Add the attributes to the attributes collection
            $AttributeCollection.Add($ParameterAttribute)

            # Generate and set the ValidateSet
            $urlGuid = "$tfsUri/DefaultCollection (I want to replace this with the value I selected from Collection parameter)/_apis/projects?api-version=1.0&`$top=500"
            $teamProjects = @(Invoke-RestMethod -UseDefaultCredentials -Method Get -uri $urlGuid).value.name

            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($teamProjects) 

            # Add the ValidateSet to the attributes collection
            $AttributeCollection.Add($ValidateSetAttribute)

            # Create and return the dynamic parameter
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName_a, [string], $AttributeCollection)
            $RuntimeParameterDictionary.Add($ParameterName_a, $RuntimeParameter)

            return $RuntimeParameterDictionary
        }

        begin 
        {
            $Collection = $PSBoundParameters[$ParameterName]
            $Project = $PSBoundParameters[$ParameterName_a]
        }

                                   
    Wednesday, April 25, 2018 10:30 PM

All replies

  • Since the Dynamic Parameters are calculated only once when PowerShell needs to find out what options are accepted, you cannot use the DynamicParam block to dynamically re-calculate the Parameter options. Depending whether the user presses tab or enter at the beginning or the end of the command, the DynamicParam block is evaluated at a time when PowerShell needs to resolve and validate the entered parameters. It might not be at the time you want/need...

    Consider this script:

    Function myTEST {
        [CmdletBinding()]
        Param(
            [String]$Environment
        )
    
        DynamicParam {
            # Set the dyanmic param name
            $ParameterName = 'Collection'
            write-warning "Calculation Dynamic Parameters"
    
            # Create the dictionary
            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
    
            # Create the collection of attributes
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
    
            # Create and set the parameter's attributes
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute  
            $ParameterAttribute.Mandatory = $true
            $ParameterAttribute.Position = 1
    
            # Add the attributes to the attributes collection
            $AttributeCollection.Add($ParameterAttribute)
    
            # Generate and set the ValidateSet
            $projectCollections = @('blue', 'yellow', 'green')
            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($projectCollections) 
    
            # Add the ValidateSet to the attributes collection
            $AttributeCollection.Add($ValidateSetAttribute)
    
            # Create and return the dynamic parameter
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
    
            return $RuntimeParameterDictionary
        }
    
        begin {
            Write-Host "Doing Something"
        }
    }

    The Write-Warning message will give give you a visual cue each time the DynamicParam scriptblock is evaluated. It's done only once or twice, not for each parameter you enter.

    What you would need to do is create parameter sets that represent all the possibilities at once and then return those possibilities in $RuntimeParameterDictionary. PowerShell will pick the parameter set depending on the user input and validate the parameters.

    Saturday, April 28, 2018 10:25 AM
    • You should be definition function using [CmdletBinding()] to use dynamic parameters.
    • Hence a Param() block is also required. Have $Environment as a parameter.

    You can check the existence of dynamic parameters within DynamicParam{} block using $PSBoundParameter automatic variable, but you cannot use the value as the dynamic param value will not be set during that time.

    Question: Why you want to  use DynamicParams here ? what is the requirement that gave you the thought of using dynamic params.

    you can make parameters prompted based on conditions using if statements within param() block.

    function test2{
        Param(
          $r,
          $t = $(if( $r -eq 1 ){Read-Host 't'})
        )
      
      
      $psboundparameters.add('t',$t)
      $psboundparameters
     
      

    Regards kvprasoon


    Sunday, April 29, 2018 5:41 PM
  • Thank you for your help! Unfortunately I cannot set the parameter sets with all the possibilities because they can change any time.
    Tuesday, May 22, 2018 9:44 PM
  • Programming is deterministic.   You cannot resolve ambiguous parameters.  You can use dynamic parameters and parameter sets to gain flexibility.  It is all a matter of the depth of your programming skills.

    Trying to overload one command with too many actions is a very bad idea in any language and especially bad in PowerShell.


    \_(ツ)_/

    Tuesday, May 22, 2018 9:48 PM
  • Consider splitting this into 2 functions:

    • one to select the environment and build the ValidationSets.
    • another to pick the options from the ValidationSets
    Function Set-Environment ($Environment)
        {
            if ($Environment -eq "Prod")
            {
                $tfsUri = "http://tfsProd"
                $teamProjects = 'lemons','apples'
                $projectCollections = 'moon','earth'
            }
            else
            {
                $tfsUri = "http://tfsTest"
                $teamProjects = 'blue','yellow'
                $projectCollections = 'pluto','mars'
            }
    
            # Generate and set the ValidateSet
            $urlCollection = "$tfsUri/_apis/projectcollections?api-version=1.0"
            #$projectCollections = @(Invoke-RestMethod -UseDefaultCredentials -Method Get -uri $urlCollection).value.name
    
            # Generate and set the ValidateSet
            $urlGuid = "$tfsUri/DefaultCollection (I want to replace this with the value I selected from Collection parameter)/_apis/projects?api-version=1.0&`$top=500"
            #$teamProjects = @(Invoke-RestMethod -UseDefaultCredentials -Method Get -uri $urlGuid).value.name
    
            $Collections = $projectCollections.ForEach( { "'{0}'" -f $_ } ) -join ','
            $Projects = $teamProjects.ForEach( { "'{0}'" -f $_ } ) -join ','
    
    
            $script = @'
    
                Function TEST {{
    
                     [CmdletBinding()]
                        Param(
                            [ValidateSet({0})]
                            [String]$Collection,
                            [ValidateSet({1})]
                            [String]$Project
                        )
                        Write-Host "You selected $Collection and $Project"
    
                }}
    '@ -f $Collections, $Projects
    
            . ([scriptBlock]::Create($Script))
    
        }

    Then you can pre-stage the TEST function, by dotsourcing the Set-Environment Function:

    PS > . Set-Environment
    
    PS > TEST -Collection mars -Project blue
    You selected mars and blue
    
    PS > . Set-Environment Prod
    
    PS > TEST -Collection earth -Project apples
    You selected earth and apples

    Thursday, May 24, 2018 10:43 AM