Powershell 枚举参数不会阻止传递多个参数

问题描述 投票:0回答:1

我假设枚举参数在默认情况下只会采用一个参数,并且在尝试传递两个或更多参数时会抛出异常。

enum Test {one; two; three}

function Test-Enum {[CmdletBinding()] param (
[Test]$number
) $number}

这按预期工作

Test-Enum -number one
Test-Enum -number two
Test-Enum -number three

我本以为传递两个参数会出现异常

Test-Enum -number one, two     # outputs two
Test-Enum -number two, one     # outputs two
Test-Enum -number one, three   # outputs three
test-Enum -number three, one   # outputs three

这些确实会触发异常

Test-Enum -number two, three   # Cannot convert value error
Test-Enum -number three, two   # Cannot convert value error

我在这里遗漏了一些明显的东西,但我无法弄清楚。如何防止使用多个参数调用 Test-Enum?

PS F:\> $PSVersionTable

Name                           Value                                                            
----                           -----                                                            
PSVersion                      5.1.19041.2673                                                   
PSEdition                      Desktop                                                          
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                          
BuildVersion                   10.0.19041.2673                                                  
CLRVersion                     4.0.30319.42000                                                  
WSManStackVersion              3.0                                                              
PSRemotingProtocolVersion      2.3                                                              
SerializationVersion           1.1.0.1                         
powershell enums parameter-passing
1个回答
0
投票

tl;博士

  • 至少到 PowerShell 7.3.4(截至撰写本文时为当前版本),PowerShell 的参数绑定器处理

    [enum]
    的派生类型,这些派生类型 not 具有
    [Flags]
    属性(这使它们成为 bit 字段 其值可以 combined) 就像它们一样。

  • 这使得它总是接受多个值,这不适合non-

    [Flags]
    枚举类型。


不幸的是,PowerShell 参数绑定器允许您将 多个 值传递给一个

[enum]
类型的参数 ,即使特定类型是是有帮助和适当的)。 如果给定多个值,它们将进行
位或
,如果结果数字不对应于定义的值,则会发生错误。
您可以从

strings

进行转换以获得等效的行为以了解参数绑定器的作用(您的枚举值的数值隐式为 [Flags] for

0

one for 1

two
 for 
2
):
three
虽然此行为对于基于 
# -> Same as: [Test] (0 -bor 1) -> two [Test] 'one, two' # -> Same as [Test] (1 -bor 2), which FAILS, because 1 -bor 2 is 3, # and 3 isn't a defined value. [Test] 'two, three'
 的枚举类型是适当且有帮助的,但对于那些不是的枚举类型,它是
not

Windows PowerShell

的解决方法:

解决方法很麻烦: 将您的参数键入

[Flags]

,这会自动阻止传递

多个
    值。
  • 使用[string]属性来验证传递的字符串是枚举中的值的名称

    [ValidateScript({ … })]
  • .
  • 为了也支持制表符完成,添加一个
    [Test]
    属性:

  • [ArgumentCompleter()]

    替代
如果使用 

enum Test { one; two; three } function Test-Enum {[CmdletBinding()] param ( [ValidateScript({ if ($_ -as [Test] -ne $null) { return $true } throw "$_ is not a valid value. Try one of: $([enum]::GetNames([Test]))" })] [ArgumentCompleter({ param($unused1, $unused2, $wordToComplete) [enum]::GetNames([Test]) -like "$wordToComplete*" })] [string] $number ) $enumVal = [Test] $number $enumVal } 派生类型不是必须的,您可以使用

[enum] alternative

: 使用辅助。实现[ValidateSet()]接口接口的类,您也可以将其与

System.Management.Automation.IValidateSetValuesGenerator

一起使用,并且在其中您可以使用[ValidateSet()]

生成有效名称:
[enum]::GetNames([Test])
    

© www.soinside.com 2019 - 2024. All rights reserved.