互斥的powershell参数

nam*_*los 24 parameters powershell optional-parameters

情景

  • 我正在使用Visual Studio 2008和.NET 3.5为Powershell 2.0编写cmdlet
  • cmdlet需要3个参数.

我想要的cmdlet语法是这样的:

cmdletname [foo|bar] p1, p2
Run Code Online (Sandbox Code Playgroud)
  • 这是因为用户必须为"-foo"或"-bar"赋予值,但不能将两者放在一起.

有效输入的例子

cmdletname -foo xxx -p1 hello  -p2 world
cmdletname -bar yyy -p1 hello  -p2 world
Run Code Online (Sandbox Code Playgroud)

无效输入的示例

cmdletname -foo xxx -bar yyy -p1 hello  -p2 world
Run Code Online (Sandbox Code Playgroud)

我的问题

  • 我的问题是如何在powershell中执行此操作,以便它为我完成所有检查 - 或者如果可能的话.
  • 我知道我可以使用foo和bar只有两个可选参数,只需手动进行错误检查.这就是我目前实施的方式.
  • 或者,我对不同方法的建议感兴趣.

Joe*_*oey 45

您可以使用parameter属性声明多个参数集.然后,您只需分配与不同参数集互斥的参数.

编辑:

这也在"about_Functions_Advanced_Parameters"中的"ParameterSetName Named Argument"部分中记录.这是使用cmdlet处理不同参数集的方式Get-Random(具有互斥参数):

> get-random -input 4 -max 77
Get-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
Run Code Online (Sandbox Code Playgroud)

以下是在函数中执行此操作的示例:

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

参数onetwo参数集在不同的参数集中,因此不能一起指定:

> exclusive_params -one foo -two bar -three third
exclusive_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
Run Code Online (Sandbox Code Playgroud)

这与Get-Random的错误相同.但我可以独立使用参数:

> exclusive_params -one foo -three third
one: foo
two:
three: third
Run Code Online (Sandbox Code Playgroud)

...要么:

> exclusive_params -two bar -three third
one:
two: bar
three: third
Run Code Online (Sandbox Code Playgroud)


Kei*_*ill 9

以下是在PowerShell社区扩展中使用从cmdlet获取的ParameterSetName的示例.顺便说一下,您可以浏览PSCX源代码.

[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;
            }
        });
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,cmdlet通常声明一个默认的ParameterSetName,它可以帮助PowerShell确定在存在歧义时要使用的"默认"参数集.稍后,如果需要,您可以通过查询this.ParameterSetName来确定哪个参数集有效,如上面的EndProcessing()覆盖中的switch语句所做的那样.


Joh*_*ger 6

我来到这里,但有一个额外的要求:可选的互斥参数。

这篇文章在这里帮助我找到了一半的答案。所以我想在这里发布完整的答案,以防有人有相同的要求。

下面的代码可用于 Powershell 脚本的顶部,以具有 4 个可选参数,其中 LaunchAsAdmin 和 LaunchAsCouponBrowser 是互斥的,而 token 和 WorkstationName 也是可选的,但可以与任何其他参数组合。

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