gpt4 book ai didi

powershell - 参数-需要一些而不是其他-正确使用参数集

转载 作者:行者123 更新时间:2023-12-02 23:10:35 25 4
gpt4 key购买 nike

因此,我正在尝试使用PowerShell,并且在理解参数时遇到了一些麻烦。从我所阅读的内容来看,如果我将一个参数指定为与另一个参数相同的位置,但是将其放置在单独的ParameterSet中,那么PowerShell仅需要存在这些参数之一。

在此示例中,按预期工作-

[CmdletBinding(DefaultParameterSetName='MultiUser')]

Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$Token,

[Parameter(Mandatory=$True,Position=2, ParameterSetName="MultiUser")]
[string]$UsernamesFile,

[Parameter(Mandatory=$True,Position=2, ParameterSetName="SingleUser")]
[string]$SingleUsername,

[Parameter(Mandatory=$False)]
[switch]$SpecialCase
)

但是,如果我想对此进行扩展,以便如上所述,您必须指定一个 token ,然后必须指定一个用户名文件 一个用户名文件,但是现在我想指定一个用户所属的组。

现在让我们假设用户必须进入两个组之一,而我不想担心以不同的方式处理用户可能输入的组名,因此我使用两个开关。我只希望用户位于一个组中,而不是两个组中,因此开关应位于相同的位置,但应位于不同的参数集中(基于我所读的内容以及以上示例的工作原理)。

所以我的第二个例子看起来像这样-
[CmdletBinding(DefaultParameterSetName='MultiUser')]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$Token,

[Parameter(Mandatory=$True,Position=2, ParameterSetName="MultiUser")]
[string]$UsernamesFile,

[Parameter(Mandatory=$True,Position=2, ParameterSetName="SingleUser")]
[string]$SingleUsername,

[Parameter(Mandatory=$True,Position=3, ParameterSetName="GroupA")]
[switch]$GroupA,

[Parameter(Mandatory=$True,Position=3, ParameterSetName="GroupB")]
[switch]$GroupB,

[Parameter(Mandatory=$False)]
[switch]$SpecialCase
)

这不能按预期工作,但是,这给了我一个错误-

New Parameters Can't Be Found

有人可以解释为什么这行不通并更正我对PowerShell参数的理解吗?

谢谢!

最佳答案

请参阅底部以获取关于OP的方法问题的解释。

准确获得您所要求的,您必须使用以下内容:

# - Make sure that parameters are NON-positional unless explicitly marked otherwise.
# - Specify the default parameter set.
[CmdletBinding(PositionalBinding=$False, DefaultParameterSetName='MultiUserA')]
Param(

# Belongs to all parameter sets.
[Parameter(Mandatory, Position=1)]
[string]$Token,

# Mandatory and positional both when combined with -GroupA or -GroupB.
[Parameter(Mandatory, Position=2, ParameterSetName='MultiUserA')]
[Parameter(Mandatory, Position=2, ParameterSetName='MultiUserB')]
[string] $UsernamesFile,

# Mandatory - but not positional - both when combined with -GroupA or -GroupB.
[Parameter(Mandatory, ParameterSetName='SingleUserA')]
[Parameter(Mandatory, ParameterSetName='SingleUserB')]
[string] $SingleUsername,

# Mandatory, whether combined with -UsernamesFile or -SingleUsername
[Parameter(Mandatory, ParameterSetName='SingleUserA')]
[Parameter(Mandatory, ParameterSetName='MultiUserA')]
[switch] $GroupA,

# Mandatory, whether combined with -UsernamesFile or -SingleUsername
[Parameter(Mandatory, ParameterSetName='SingleUserB')]
[Parameter(Mandatory, ParameterSetName='MultiUserB')]
[switch] $GroupB,

# Belongs to all parameter sets. Non-mandatory by default.
[switch] $SpecialCase

)

如你看到的,
  • 您需要定义4个参数集,这些参数集等于所有users-file-vs.-single-user和groupA-vs.-group-B的组合。
  • 您需要将每个参数分配给多个参数集,并选择适当的子集。
  • 请注意,每个[Parameter(...)]属性只能指定1个参数集,在此指定的任何其他属性MandatoryPosition,...-仅在给定参数集的上下文中适用于该参数。

  • 当您使用 -?调用脚本(或将其传递给 Get-Help)时,您将看到生成的语法图:
    script.ps1 [-Token] <string> [-UsernamesFile] <string> -GroupA [-SpecialCase] [<CommonParameters>]
    script.ps1 [-Token] <string> [-UsernamesFile] <string> -GroupB [-SpecialCase] [<CommonParameters>]
    script.ps1 [-Token] <string> -SingleUsername <string> -GroupB [-SpecialCase] [<CommonParameters>]
    script.ps1 [-Token] <string> -SingleUsername <string> -GroupA [-SpecialCase] [<CommonParameters>]

    但是,由于以下原因,这种 方法是不明智的:
  • 您不应具有必需的[switch]参数,因为根据定义它们是可选的。
  • 当您调用不带参数的脚本进行交互式参数输入时,PowerShell将不允许您指定开关值(没有尝试过的值:不是truefalse10,...-尝试使用./script someToken someFile)
  • ./script.ps1 someToken -SingleUsername someUser提供一般错误消息(Parameter set cannot be resolved using the specified named parameters.),而不是专门指出缺少-GroupA-GroupB,因为PowerShell无法知道您是指参数集SingleUserA还是SingleUserB
  • 相比之下,./script someToken someFile(带有隐含的-UsernamesFile)是明确的,因为MultiUserA是默认参数集,但是由于-GroupA开关是强制性的,因此仍然会提示您输入其值。
  • 最后但并非最不重要的一点,正如Mathias R. Jessen所指出的那样,使用不同的互斥开关(-GroupA-GroupB)不能很好地扩展,因为快速添加更多的-Group*开关会使必须分别反射(reflect)在自己参数中的组合数量设置难以管理-请参阅下文了解如何避免这种情况。


  • Mathias R. Jessen's helpful answer所指出的, 更好的方法是对目标组使用 单个参数,即 仅接受给定值中的值, [ValidationAttribute]可以确保:
    [CmdletBinding(PositionalBinding=$False, DefaultParameterSetName='MultiUser')]
    Param(

    [Parameter(Mandatory, Position=1)]
    [string] $Token,

    [Parameter(Mandatory, Position=2, ParameterSetName='MultiUser')]
    [string] $UsernamesFile,

    [Parameter(Mandatory, ParameterSetName='SingleUser')]
    [string] $SingleUsername,

    # Single -Group parameter that only accepts values 'GroupA' and 'GroupB'
    # Input validation is case-INsensitive, as usual.
    [Parameter(Mandatory)]
    [ValidateSet('GroupA', 'GroupB')]
    [string] $Group,

    [switch] $SpecialCase

    )

    这为我们提供了以下语法图(请注意,未反射(reflect) -Group的有效值集):
    script.ps1 [-Token] <string> [-UsernamesFile] <string> -Group <string> [-SpecialCase] [<CommonParameters>]
    script.ps1 [-Token] <string> -SingleUsername <string> -Group <string> [-SpecialCase] [<CommonParameters>]
  • 这会将所需参数集的数量减少到2。
  • 它支持交互式输入组名(尽管遗憾的是,提供无效的名称会中止调用)。
  • 如果您省略-Group,那么./script.ps someToken someFile./script.ps someToken -SingleUserName someUser现在的行为相同:它们提示输入-Group值。
  • 尽管必须键入-Group,并且调用值比使用不同的开关-GroupA-GroupB稍微麻烦一些,
  • 是更可扩展的方法,如果组的数量随时间增长,
  • 选项卡补全确实可以扩展/循环显示有效值。


  • 至于您的原始方法的 问题:
  • 正如Clijsters所指出的,您尝试调用./script.ps1 -Token a -UsernamesFile someFile -GroupA的尝试失败,因为:
  • PowerShell需要明确地将给定的参数组合解析为参数集。
  • -GroupA仅属于参数集GroupA,而-UsersnameFile仅属于参数集MultiUser,因此这些参数实际上是互斥的,PowerShell无法确定要使用的参数集。
  • 默认情况下,所有非开关参数均为位置参数-除非您使用[CmdletBinding(PositionalBinding=$False,...)]显式停用它,否则只有显式标记为[Parameter(...)]属性的各个Position属性才变为位置参数。
  • 另外,将[switch]参数设置为无位置是没有意义的,因为根据定义它们是非位置的:您必须始终(明确地)指定其名称,并且可以将它们放置在任何位置。
  • 关于powershell - 参数-需要一些而不是其他-正确使用参数集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43018188/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com