Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional PowerShell parameters

Is there a way to have some of the parameters mandatory based on some condition (for example, if one of the parameters is absent or false) in a PowerShell function?

My idea is to be able to call a function in two ways. A concrete example is a function that gets a list from SharePoint - I should be able to call it with relative URL of the list (one and only parameter) OR with a web URL and a list display name (two parameters, both mandatory, but only if list relative URL is not used).

like image 305
jumbo Avatar asked May 25 '12 05:05

jumbo


People also ask

How do I use if condition in PowerShell?

The syntax of If statements in PowerShell is pretty basic and resembles other coding languages. We start by declaring our If statement followed by the condition wrapped in parentheses. Next, we add the statement or command we want to run if the condition is true and wrap it in curly brackets.

How do you use dynamic parameters in PowerShell?

These parameters are added at runtime and are referred to as dynamic parameters because they're only added when needed. For example, you can design a cmdlet that adds several parameters only when a specific switch parameter is specified. Providers and PowerShell functions can also define dynamic parameters.

How do I add parameters to a PowerShell script?

How do I pass parameters to PowerShell scripts? Passing arguments in PowerShell is the same as in any other shell: you just type the command name, and then each argument, separated by spaces. If you need to specify the parameter name, you prefix it with a dash like -Name and then after a space (or a colon), the value.

How do I create a switch parameter in PowerShell?

To create a switch parameter in a function, specify the switch type in the parameter definition. Switch parameters are easy to use and are preferred over Boolean parameters, which have a less natural syntax for PowerShell. For example, to use a switch parameter, the user types the parameter in the command.


2 Answers

As Christian indicated, this can be accomplished via ParameterSetNames. Take a look at this example:

function Get-MySPWeb {
    [CmdletBinding(DefaultParameterSetName="set1")]
    param (
        [parameter(ParameterSetName="set1")] $RelativeUrl,
        [parameter(ParameterSetName="set2")] $WebUrl,
        [parameter(ParameterSetName="set2", Mandatory=$true)] $DisplayName
    )
    Write-Host ("Parameter set in action: " + $PSCmdlet.ParameterSetName)
    Write-Host ("RelativeUrl: " + $RelativeUrl)
    Write-Host ("WebUrl: " + $WebUrl)
    Write-Host ("DisplayName: " + $DisplayName)
}

If you run it with -RelativeUrl Foo it will bind to "set1". If you call this function without any parameters it will also bind to "set1".

(Note - when no parameters are provided in PowerShell v3 (with Windows 8 consumer preview) it will bind to "set1", however it will error binding in PowerShell v2 unless you add [CmdletBinding(DefaultParameterSetName="set1")] to the parameter block. Thanks @x0n for the DefaultParameterSetName tip!)

If you try to run it with a parameter value from both sets you will get an error.

If you run it with -WebUrl Bar it will prompt you for a parameter value for DisplayName, because it's a mandatory parameter.

like image 59
Andy Arismendi Avatar answered Oct 14 '22 06:10

Andy Arismendi


There is a much more powerful option, called dynamic parameters, which allows to dynamically add parameters depending on the value of other parameters or any other condition.

You must structure your script in a different way, declaring the regular parameters as usual, and including a DynamicParam block to create dynamic parameters, a Begin block to initialize variables using the dynamic parameters , and a Process block with the code run by the script, which can use regular parameters, and variables initialized in Begin. It looks like this:

param( 
  # Regular parameters here
)

DynamicParam {
  # Create a parameter dictionary
  $runtimeParams = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

  # Populate it with parameters, with optional attributes
  # For example a parameter with mandatory and pattern validation
  $attribs = New-Object  System.Collections.ObjectModel.Collection[System.Attribute]

  $mandatoryAttrib = New-Object System.Management.Automation.ParameterAttribute
  $mandatoryAttrib.Mandatory = $true
  $attribs.Add($mandatory)

  $patternAttrib = New-Object System.Management.Automation.ValidatePatternAttribute('your pattern here')
  $attribs.Add($patternAttrib)

  # Create the parameter itself with desired name and type and attribs
  $param = New-Object System.Management.Automation.RuntimeDefinedParameter('ParameterName', String, $attribs)

  # Add it to the dictionary
  $runtimeParams.Add('ParameterName', $param)

  # Return the dictionary
  $ruintimeParams
}

Begin {
  # If desired, move dynamic parameter values to variables
  $ParameterName = $PSBoundParameters['ParameterName']
}

Process {
  # Implement the script itself, which can use both regular an dynamic parameters
}

Of course, the interesting part is that you can add conditions on the DynamicParam section and the Begin section to create different parameters depending on anything, for example other parameter values. The dynamic parameters can have any name, type (string, int, bool, object...) an attributes (mandatory, position, validate set...), and they are created before the execution of the script so that you get parameter tab completion (IntelliSense) in any environment which supports it, like the PowerShell console, the PowerShell ISE or the Visual Studio Code editor.

A typical example would be to create a different set of dynamic parameters depending on the value of a regular parameter, by using a simple if in the DynamicParam section.

Google "PowerShell dynamic parameters" for extra information, like showing help for dynamic parameters. For example:

  • PowerShell Magazine Dynamic Parameters in PowerShell
like image 23
JotaBe Avatar answered Oct 14 '22 06:10

JotaBe