powershellparametersoptional-parameters

Mutually exclusive powershell parameters


SCENARIO

my intended grammar of the cmdlet is something like this:

cmdletname [foo|bar] p1, p2

EXAMPLE OF VALID INPUT

cmdletname -foo xxx -p1 hello  -p2 world
cmdletname -bar yyy -p1 hello  -p2 world

EXAMPLE OF INVALID INPUT

cmdletname -foo xxx -bar yyy -p1 hello  -p2 world

MY QUESTION


Solution

  • 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.