Need help to make dependent parameters

This topic contains 10 replies, has 4 voices, and was last updated by Profile photo of Jaap Brasser Jaap Brasser 2 years, 1 month ago.

  • Author
    Posts
  • #23949
    Profile photo of
    Anonymous

    Hi Guys,
    I need your help to write a function with dependent parameters.

    In this below example, if the switch 'NO_Fav_things' is $true then the parameter 'FavoriteCar' should not come when user gives tabs; if technically this is not possible then at least it should through an error.

    [CmdletBinding()] 
    param( 
         [string]$Age, 
         [string]$Sex, 
         [string]$Location,
         [switch]$NO_Fav_things,      
         [string]$FavoriteCar
    )
    
  • #23950
    Profile photo of Don Jones
    Don Jones
    Keymaster

    You might be able to do something with dynamic parameters, but really, what you're asking for isn't a correct pattern in PowerShell. The shell doesn't use one parameter to 'enable' another. You should provide your -FavoriteChar as an optional parameter; if it isn't provided, then internally you would set a variable to False if needed.

  • #23955
    Profile photo of Raymond Slieff
    Raymond Slieff
    Participant

    Yeah it might just be easier on this one to set the default value of $FavoriteCar to something arbitrary, or empty, then just test against it, if it is the default value, basically ignore it, otherwise act upon it, and then you do not need the $NO_Fav_things switch at all.

  • #23957
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Actually, you don't need to use a default value. $PSBoundParameters.ContainsKey('FavoriteChar') will return True or False if the parameter was used, so you'd use that to test. That's a better pattern than testing for an arbitrary default value. Technically, if you provide a default value, then the parameter always "exists."

    But you should definitely do that vs. having a second switch parameter.

  • #23958
    Profile photo of Raymond Slieff
    Raymond Slieff
    Participant

    Thanks for that, looks like either I've just overlooked something or missed it in my learning on PowerShell, so now I have just another item added to my own arsenal.

  • #24161
    Profile photo of
    Anonymous

    Unfortunately I am unable to understand dynamic parameters. Some how I grabbed some helpful examples and re-wrote the code to my requirements. But its not giving the required outputs. Please help me to arrange this code.

    My requirement is :

    I have 3 parameters. (1) DAG (2) ExcludeNode (3) Node. The below are the conditions
    1. DAG can take inputs alone, i.e., with out ExcludeNode and Node parameter should be $Null
    2. ExcludeNode should accept input only if DAG != $null and Node=$Null
    3. Node should accept inputs only if DAG, ExcludeNode 's are $Null

    The problem with the below code, after executing the code I am able to see only one parameter that is DAG. But cannot find any further parameters.

    Function check
    {
    	[CMDLetBinding()]
    	param()
    	#		[parameter(MAndatory=$False,ValueFromPipeline=$False,Position=0)][String[]]$DAG,
    	#		[parameter(MAndatory=$False,ValueFromPipeline=$False,Position=1)][String[]]$ExcludeNode,
    	#		[parameter(MAndatory=$False,ValueFromPipeline=$False,Position=2)][String[]]$Node		
    	#)
    	DynamicParam
        {
            if ($Node -eq $Null)
            {
                $attributes = new-object System.Management.Automation.ParameterAttribute
                $attributes.ParameterSetName = "__AllParameterSets"
                $attributes.Mandatory = $false
                $attributeCollection = new-object `
                    -Type System.Collections.ObjectModel.Collection[System.Attribute]
                $attributeCollection.Add($attributes)
    
                $dynParam1 = new-object `
                    -Type System.Management.Automation.RuntimeDefinedParameter("DAG", [String[]], $attributeCollection)
    
                $paramDictionary = new-object `
                    -Type System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add("DAG", $dynParam1)
                return $paramDictionary
            }
    		if ($Node -eq $Null -and $DAG -ne $Null)
            {
                $attributes = new-object System.Management.Automation.ParameterAttribute
                $attributes.ParameterSetName = "__AllParameterSets"
                $attributes.Mandatory = $false
                $attributeCollection = new-object `
                    -Type System.Collections.ObjectModel.Collection[System.Attribute]
                $attributeCollection.Add($attributes)
    
                $dynParam1 = new-object `
                    -Type System.Management.Automation.RuntimeDefinedParameter("ExcludeNode", [String[]], $attributeCollection)
    
                $paramDictionary = new-object `
                    -Type System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add("ExcludeNode", $dynParam2)
                return $paramDictionary
            }
    		if ($DAG -eq $Null -and $ExcludeNode -eq $Null)
            {
                $attributes = new-object System.Management.Automation.ParameterAttribute
                $attributes.ParameterSetName = "__AllParameterSets"
                $attributes.Mandatory = $false
                $attributeCollection = new-object `
                    -Type System.Collections.ObjectModel.Collection[System.Attribute]
                $attributeCollection.Add($attributes)
    
                $dynParam1 = new-object `
                    -Type System.Management.Automation.RuntimeDefinedParameter("Node", [String[]], $attributeCollection)
    
                $paramDictionary = new-object `
                    -Type System.Management.Automation.RuntimeDefinedParameterDictionary
                $paramDictionary.Add("Node", $dynParam3)
                return $paramDictionary
            }
        }
    	Begin
    	{
    	}
    	PROCESS
    	{
    		$DAG[0]
    		$ExcludeNode[0]
    		$Node[0]
    	}
    	END{}
    }
    
  • #24162
    Profile photo of Jaap Brasser
    Jaap Brasser
    Participant

    So one thing you are doing wrong is that your param () statement does not encapsulate all the static and dynamic parameters. Further more based on what you are saying you don't need dynamic parameters you could simply use parameter sets. So what I have done is the following:

      Created two parameters sets, DAG and Node (names are cosmetic feel free to change it
      For the DAG parameter set I have set -Dag as mandatory and -ExcludeNode as non-mandatory
      The second parameter set only has node and the function will fail if either Dag or ExcludeNode are included

    Here is the code I created for you, let me know if it makes sense and if it works as expected:


    Function Test-Param {
    [CMDLetBinding()]
    param(
    [parameter(ParameterSetName="DAG",
    MAndatory=$true,
    ValueFromPipeline=$False,
    Position=0)]
    [String[]]$DAG,
    [parameter(ParameterSetName="DAG",
    MAndatory=$False,
    ValueFromPipeline=$False,
    Position=1)]
    [String[]]$ExcludeNode,
    [parameter(ParameterSetName="Node",
    MAndatory=$False,
    ValueFromPipeline=$False,
    Position=0)]
    [String[]]$Node
    )
    }

  • #24163
    Profile photo of
    Anonymous

    Superb !! that worked fine in PowerShell 4.0 but not working as expected in 2.0. Any alternate or work around by changing the code for this pls..?
    The target machines cannot be upgraded to PS version >2.0

    On other hand if we cannot write the code in 2.0 to make it work like 4.0, then I am okay even if we can capture and condition the error and then produce my own write-error text. here I am not sure where to try-catch the error ! 🙁 . PFA error.

  • #24167
    Profile photo of Jaap Brasser
    Jaap Brasser
    Participant

    That is because parameter sets as well as dynamic parameters were introduced in PowerShell version 3, so if you would like to support this in PowerShell 2.0 you would have to write it yourself. As for dynamic parameters, this is when you want parameters or arguments for your parameter to be dependent on an outside source. For example if the arguments for the -DAG parameter are stored in an external csv which changes on a regular basis then you could populate the potential arguments using dynamic parameters.

    To write this in PowerShell 2.0 it would be something along these lines, I use a switch statement here in which I use the -and and the -not operators to match your logic:

    Function Test-Param {
        [CMDLetBinding()]
        param(
            [String[]]$DAG,
            [String[]]$ExcludeNode,
            [String[]]$Node
        )
    
    $CustomErrorMessage = "1. DAG can take inputs alone, i.e., with out ExcludeNode and Node parameter should be $Null
    2. ExcludeNode should accept input only if DAG != $null and Node=$Null
    3. Node should accept inputs only if DAG, ExcludeNode 's are $Null"
    
        switch ($true) {
            {($DAG) -and (-not $Node)} {'yay'}
            {($ExcludeNode) -and ($DAG) -and (-not $Node)} {'yay2'}
            {($Node) -and (-not $DAG) -and (-not $ExcludeNode)} {'yay3'}
            Default {Write-Warning $CustomErrorMessage}
        }
    }
  • #24168
    Profile photo of
    Anonymous

    thnx bro, thnx a lot. let me implement and see if I need anything else. at a glance its good now.

  • #24170
    Profile photo of Jaap Brasser
    Jaap Brasser
    Participant

    No problem, let me know if you need any additional help with any of this.

You must be logged in to reply to this topic.