0

I am attempting to use two Dynamic Parameters in the same cmdlet. The problem is that I would like the second dynamic parameter to use the first parameter to populate the result set.

For example the syntax for using the command could be something like this -

Get-MSRP -Manufacturer Jeep -Trim Rubicon

'Manufacturer' is a dynamic parameter that looks at a file on the disk to populate values for the user. I would 'Trim' to consume the 'Manufacturer' option that the user chose to create a result set of 'Trim'.

My 'Manufacturer' is working correctly but I believe that the value which the user has chosen isn't available when the code for the DynamicParam I've created for 'Trim', has been ran.

Any help?

function Get-MSRP{
    [cmdletbinding()]
    param()
    DynamicParam{
        $Param1 = "Manufacturer",0,{GC c:\temp\manufacturers.txt},$False
        $Param2 = "Trim",1,{GC c:\temp\$Manufacturer\Trim.txt},$False
        Get-DynamicParameterSet $Param1,$Param2
    }
    begin{
        $Manufacturer = $PSBoundParameters["Manufacturer"]
        $Trim = $PSBoundParameters["Trim"]
    }
    process{
        return Invoke-Sqlcmd -Database 'db' -ServerInstance 'server' -Query 
        "Select MSRP from pricing.MSRP where Manufacturer = '$Manufacturer' 
        and Trim = '$Trim'"
    }
}


function Get-DynamicParameterSet{
    param($Params)
    $RuntimeParameterDictionary = New-Object 
System.Management.Automation.RuntimeDefinedParameterDictionary
    if($Params[0].GetType().Name -eq "String" ){
        Write-Debug "Single Param to build"
        $RuntimeParameterDictionary = BuildSet $Params[0] $Params[1] 
$([Scriptblock]$Params[2]) $Params[3] $Params[4] $RuntimeParameterDictionary
    }else{
        foreach($Param in $Params){
            $RuntimeParameterDictionary = BuildSet $Param[0] $Param[1] 
            $([Scriptblock]$Param[2]) $Param[3] $Param[4] 
            $RuntimeParameterDictionary
        }
    }
    return $RuntimeParameterDictionary
}

function BuildSet{
    param(
        $ParameterName,
        [int]$Position,
        [ScriptBlock]$scriptBlock,
        $Mandatory,
        $SetNames,
          [System.Management.Automation.RuntimeDefinedParameterDictionary]$RuntimeParameterDictionary)

    Write-Debug "Setting up $ParameterName"
    $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]

    $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
    $ParameterAttribute.Mandatory = $Mandatory
    $ParameterAttribute.Position = $Position
    $ParameterAttribute.ParameterSetName = $SetNames

    $AttributeCollection.Add($ParameterAttribute)
    Write-Debug "Generating result set"
    $arrSet = Invoke-Command $scriptBlock
    Write-Debug "Generated as $arrSet"
    $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($arrSet)

    $AttributeCollection.Add($ValidateSetAttribute)

    $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
    $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
    return $RuntimeParameterDictionary

}


Minimal & Verifiable

function Get-MSRP{
    [cmdletbinding()]
    param()
    DynamicParam{
        $Param1 = "Manufacturer",0,{GC c:\temp\manufacturers.txt},$False
        $Param2 = "Trim",1,{gci c:\temp\$Manufacturer},$False
        Get-DynamicParameterSet $Param1,$Param2
    }
    begin{
        $Manufacturer = $PSBoundParameters["Manufacturer"]
        $Trim = $PSBoundParameters["Trim"]
    }
    process{
        return Invoke-Sqlcmd -Database 'db' -ServerInstance 'server' -Query 
        "Select MSRP from pricing.MSRP where Manufacturer = '$Manufacturer' 
        and Trim = '$Trim'"
    }
}


function Get-DynamicParameterSet{
   param($Params)

   $RuntimeParameterDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
   foreach($Param in $Params){

        $ParameterName = $Param[0]
        [int]$Position = $Param[1]
        [ScriptBlock]$scriptBlock = $([Scriptblock]$Param[2])
        $Mandatory = $Param[3]
        $SetNames =$Param[4]

        $AttributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()

        $ParameterAttribute = [System.Management.Automation.ParameterAttribute]::new()
        $ParameterAttribute.Mandatory = $Mandatory
        $ParameterAttribute.Position = $Position
        $ParameterAttribute.ParameterSetName = $SetNames

        $AttributeCollection.Add($ParameterAttribute)

        $arrSet = Invoke-Command $scriptBlock

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

        $AttributeCollection.Add($ValidateSetAttribute)

        $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
        $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
    }
    return $RuntimeParameterDictionary
}
3
  • 2
    Please show your code! Commented Jan 19, 2018 at 16:12
  • 2
    See How to Ask and provide a minimal reproducible example. Commented Jan 19, 2018 at 16:18
  • I can work on a minimum / verifiable, although they will be extremely similar to this code block. Are there any other suggestions that you have? Commented Jan 23, 2018 at 17:00

2 Answers 2

0

After some research, i've found that you cannot have this type of 'Compound dynamic parameter' in powershell where the second dynamic parameter uses a variable output from the users first dynamic parameter. The reason being that the values aren't bound to dynamic parameter until the command is ran.

Another note on Dynamic parameters, the ValueFromPipeline order is not respected when using them!

Sign up to request clarification or add additional context in comments.

Comments

0

I had a similar requirement for my function. Here you can read how I solved the problem. You can extend dynamic parameters depending on the values of the parameters. Take a look: https://stackoverflow.com/a/79227324/4879264

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.