Search code examples
powershellpowershell-core

Dynamic parameters in Powershell based on value of other parameter


[CmdletBinding()]
param (
    [Parameter(Mandatory=$true,Position=0)]
    [string]
    $subscription,

    [Parameter(Mandatory=$false)]
    [string]
    $applicationId,

    [Parameter(Mandatory=$false)]
    [string]
    $clientSecret,

    [Parameter(Mandatory=$true,Position=1)]
    [string]
    $resourceGroupName,

    [Parameter(Mandatory=$true,Position=2)]
    [string]
    $apimServiceName,

    [Parameter(Mandatory=$true,Position=3)]
    [string]
    $policyfilePath,

    [Parameter(Mandatory=$true,Position=4)]
    [ValidateSet('global','product','api','operation', IgnoreCase = $true)]
    [string]
    $scope='global',
    
    [Parameter(Mandatory=$true,Position=5)]
    [string]
    $apiIdOrProductId

    #THIS IS THE PARAMETER WHICH I WANT TO MAKE MANDATORY IF VALUE OF PREVIOUS PARAMETER $scope = "OPEARTION"
    #[Parameter(Mandatory=$false)]
    #[string]
    #$operationname
)

DynamicParam {
    if ($scope -eq "OPERATION" -or $scope -eq "operation") {
         #create a new ParameterAttribute Object
         Write-Host "Called test"
         Write-Host $scope
         $operationAttribute = New-Object System.Management.Automation.ParameterAttribute
         $operationAttribute.Mandatory = $true
         $operationAttribute.Position = 6
         
         #create an attributecollection object for the attribute we just created.
         $attributeCollection = new-object System.Collections.ObjectModel.Collection[System.Attribute]

         #add our custom attribute
         $attributeCollection.Add($operationAttribute)

         #add our paramater specifying the attribute collection
         $operationName = New-Object System.Management.Automation.RuntimeDefinedParameter('operationname', [String], $attributeCollection)

         #expose the name of our parameter
         $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
         $paramDictionary.Add('operationname', $operationName)
         return $paramDictionary
   }

}

I cannot get the dynamic parameter to work which is dependent on a previous parameter "scope". It just skips over when I run the PS script. Please advice what I'm doing wrong?


Solution

    • Your code only works if you pass an argument to your -scope parameter directly on the command line.

    • If you let PowerShell prompt you for a -scope argument, based on the parameter's Mandatory property, your code cannot work, because the dynamicparam block runs before such automatic prompts.

    Since you're assigning a default value to $scope, 'global' (which doesn't make sense in combination with Mandatory=$true), one option is to simply remove the Mandatory property:

    • This will default to 'global' in the absence of a (possibly positional) -scope argument, in which case you know that the additional parameter isn't required.

    • If an argument is specified, then your dynamicparam block will work as intended.

    However, this also requires you to place the mandatory $apiIdOrProductId parameter declaration before $scope (swap Position values 4 and 5)