互斥的 powershell 参数

发布于 2024-08-11 08:32:51 字数 663 浏览 4 评论 0原文

场景

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

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

cmdletname [foo|bar] p1, p2
  • 这意味着用户必须为“-foo”或“-bar”提供一个值,但不能同时提供两者。

有效输入的示例

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

无效输入的示例

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

我的问题

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

SCENARIO

  • I'm writing a cmdlet for Powershell 2.0 using Visual Studio 2008 and .NET 3.5
  • the cmdlet requires 3 arguments.

my intended grammar of the cmdlet is something like this:

cmdletname [foo|bar] p1, p2
  • That reads as the user must give a value for "-foo" or "-bar" but can't give both together.

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

  • My question is on how to do this in powershell so that it does all the checking for me - or if that is possible at all.
  • I know I can use just have two optional parameters for foo and bar and simply do the error checking manually. That's how I have it implemented currently.
  • Alternatively, I am interested in suggestions for different approaches.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

玩物 2024-08-18 08:32:51

您可以使用参数属性来声明多个参数套。然后,您只需将互斥的参数分配给不同的参数集即可。

编辑:

这也记录在“about_Functions_Advanced_Parameters”中的“ParameterSetName 命名参数”部分下。这是使用 Get-Random(具有互斥参数)等 cmdlet 处理不同参数集的方式:

> 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

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

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

参数 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

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

> exclusive_params -one foo -three third
one: foo
two:
three: third

...或者:

> exclusive_params -two bar -three third
one:
two: bar
three: third

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

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

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

> exclusive_params -one foo -three third
one: foo
two:
three: third

...or:

> exclusive_params -two bar -three third
one:
two: bar
three: third
如日中天 2024-08-18 08:32:51

以下是使用从 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;
            }
        });
    }
    ...
}

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

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.

娇柔作态 2024-08-18 08:32:51

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

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

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

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

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  
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文