Mutually exclusive powershell parameters Mutually exclusive powershell parameters powershell powershell

Mutually exclusive powershell parameters


You can use the parameter attribute to declare multiple parameter sets. You then simply assign parameters that are mutually exclusive to different parameter sets.

EDIT:

This is also documented in 'about_Functions_Advanced_Parameters', under the section "ParameterSetName Named Argument". This is how different sets of parameters is handled with cmdlets like Get-Random (which has mutually exclusive parameters):

> get-random -input 4 -max 77Get-Random : Parameter set cannot be resolved using the specified named parameters.At line:1 char:11+ get-random <<<<  -input 4 -max 77    + CategoryInfo          : InvalidArgument: (:) [Get-Random], ParameterBindingException    + FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.GetRandomCommand

Here's an example of doing it in a function:

function exclusive_params() {     param(         [parameter(ParameterSetName="seta")]$one,        [parameter(ParameterSetName="setb")]$two,         $three     )    "one: $one"; "two: $two"; "three: $three" }

The parameters one and two are in different parameter sets, so they cannot be specified together:

> exclusive_params -one foo -two bar -three thirdexclusive_params : Parameter set cannot be resolved using the specified named parameters.At line:1 char:17+ exclusive_params <<<<  -one foo -two bar -three third    + CategoryInfo          : InvalidArgument: (:) [exclusive_params], ParameterBindingException    + FullyQualifiedErrorId : AmbiguousParameterSet,exclusive_params

Which is the same error I got with Get-Random. But I can use the parameters independently:

> exclusive_params -one foo -three thirdone: footwo:three: third

...or:

> exclusive_params -two bar -three thirdone:two: barthree: third


Here's an example of using ParameterSetName taken from a cmdlet in the PowerShell Community Extensions. BTW, for ideas you can browse the PSCX source code.

[Cmdlet(VerbsCommon.Set, PscxNouns.Clipboard,         DefaultParameterSetName = ParamSetText)][Description("Copies the item in the system clipboard.")][RelatedLink(typeof(GetClipboardCommand))][RelatedLink(typeof(OutClipboardCommand))][RelatedLink(typeof(WriteClipboardCommand))]public class SetClipboardCommand : ClipboardCommandBase{    ... fields elided    const string ParamSetRtf = "Rtf";    const string ParamSetHtml = "Html";    const string ParamSetText = "Text";    const string ParamSetFiles = "Files";    const string ParamSetImage = "Image";    .     [AllowNull]    [Parameter(ValueFromPipeline = true, ParameterSetName = ParamSetImage)]    public Image Image { get; set; }    .     [AllowNull]    [AllowEmptyCollection]    [Parameter(ValueFromPipeline = true, ValueFromRemainingArguments = true,               ParameterSetName = ParamSetFiles)]    public FileSystemInfo[] Files { get; set; }    .     [AllowNull]    [AllowEmptyString]    [Parameter(ValueFromPipeline = true, ValueFromRemainingArguments = true,               ParameterSetName = ParamSetText)]    public string Text { get; set; }    .     [Parameter(ValueFromPipeline = true, ValueFromRemainingArguments = true,               ParameterSetName = ParamSetHtml)]    public string Html { get; set; }    .             [Parameter(ValueFromPipeline = true, ValueFromRemainingArguments = true,               ParameterSetName = ParamSetRtf)]    public string Rtf { get; set; }    .     protected override void ProcessRecord()    {        ...    }    .    protected override void EndProcessing()    {        ExecuteWrite(delegate        {            switch (ParameterSetName)            {                case ParamSetFiles:                    if (Paths.Count == 0)                        WinFormsClipboard.Clear();                    else                        WinFormsClipboard.SetFileDropList(_paths);                    break;                case ParamSetImage:                    if (Image == null)                        WinFormsClipboard.Clear();                    else                        WinFormsClipboard.SetImage(_image);                    break;                case ParamSetRtf:                    SetTextContents(Rtf, TextDataFormat.Rtf);                    break;                case ParamSetHtml:                    SetTextContents(Html, TextDataFormat.Html);                    break;                default:                    SetTextContents(Text, TextDataFormat.UnicodeText);                    break;            }        });    }    ...}

Note that the cmdlet typically declares a default ParameterSetName that helps PowerShell determine the "default" parameter set to use when there is ambiguity. Later on, if needed, you can determine which parameter set is in force by querying this.ParameterSetName as the switch statement does above in the EndProcessing() override.


I came here but with an additional requirement: Optional mutual exclusive parameters.

This post here helped me to find half of the answer. So I thought to post here the full answer in case someone has the same requirements.

The code below can be used at the top of a Powershell script to have 4 optional parameters of which LaunchAsAdmin and LaunchAsCouponBrowser are mutually exclusive while token and WorkstationName are also optional but can be combined with any other parameter.

[CmdletBinding(DefaultParametersetName="default")]                  Param(    [string]$token,    [string]$WorkstationName,    [parameter(ParameterSetName="seta")][switch]$LaunchAsAdmin,    [parameter(ParameterSetName="setb")][switch]$LaunchAsCouponBrowser  )