我有一个旨在接收命名参数的脚本,并且在未命名或命名错误的情况下,我想提供一些错误检查,并且我觉得有些奇怪。
脚本以这样的参数块开头
param (
[string][Alias("s")] $sets,
[string][Alias("l")] $location, # /MLF #
[switch][Alias("c")] $conform,
[string][Alias("eM")] $exitMode,
[string][Alias("iM")] $interactionMode,
[string][Alias("lM")] $logMode,
[switch][Alias("tM")] $testMode,
[parameter(ValueFromRemainingArguments = $true)][object[]]$extraParameters = @()
)
然后我可以使用它来获取无关参数数据的数组并去除值,因此可以为用户提供无关参数或命名错误的列表。一切都很好。
if ($extraparameters.count -gt 0) {
$invalidArguments = New-Object Collections.ArrayList
foreach ($namedParameter in $extraParameters) {
if ($namedParameter.StartsWith('-')) {
$invalidArguments.Add($namedParameter) > $null
}
}
Write-PxLog "{initError-[cf][2]}_Invalid arguments '$($invalidArguments -join ', ')'"
$proceed = $false
}
稍后,我还将验证某些参数的值,例如在此处,如果未提供日志模式,则将提供默认日志模式;在未提供日志模式的情况下,将验证提供的日志模式;并记录错误。 。一切正常。
if ($logMode) {
if ($validLogMode = Resolve-PxLogMode $logMode) {
$logMode = $validLogMode
} else {
Write-PxLog "{initError-[cf][2]}_Invalid -logMode '$($logMode)'"
$logMode = $null
$proceed = $false
}
} else {
$logMode = 'Terse'
}
所有这些都带有预期的命名参数,因此命令行可能是
sets:Proxy -logMode:Verbose -eM:exitConsole
一切都很好。
但是,当我尝试针对未命名的参数进行验证时,一切都崩溃了。如果我在命令行上使用
Proxy exitConsol verbose
我希望$args.count
为3,我希望exitMode,interactionMode和logMode为默认值。但是$args.count
为0,甚至更奇怪,exitMode也会针对“详细”进行验证。我的假设是Conform参数,它是一个开关,将其抛出,因此$ exitMode接受提供的第三个字符串。
那么,如何强制命名参数并测试未命名的参数,以便提供有意义的错误?我希望$ args可以解决问题,但是似乎如果您使用Param()块,则不会填充$ args,并且未指定位置的参数仍可以是位置参数,并使用{{1} }只是允许将该位置定义为与参数本身的定义顺序不同?
答案 0 :(得分:1)
要要求输入除$extraParameters
以外的所有参数值及其名称,只需在[CmdletBinding(PositionalBinding=$false)]
关键字之前添加属性param
:
[CmdletBinding(PositionalBinding=$false)]
param (
[string][Alias("s")] $sets,
[string][Alias("l")] $location, # /MLF #
[switch][Alias("c")] $conform,
[string][Alias("eM")] $exitMode,
[string][Alias("iM")] $interactionMode,
[string][Alias("lM")] $logMode,
[switch][Alias("tM")] $testMode,
[parameter(ValueFromRemainingArguments = $true)][object[]]$extraParameters = @()
)
要访问传递给函数或命令的参数,应在代码内部使用以下内容:
$PSBoundParameters
[CmdletBinding(PositionalBinding=$false)]
PositionalBinding
属性的CmdletBinding
自变量
允许您控制默认设置。如果您不使用
参数,那么您已经有效地将PositionalBinding
设置为
$true
。保留值$true
将允许未命名的参数
传递给您的命令。 $PSBoundParameters
$PSBoundParameters
包含一个传递给您的命令或脚本的参数字典。只能在声明参数的范围内访问它。param
关键字声明的参数。-computer
的参数,则可以从$PSBoundParameters['Computer']
在函数中访问该值。$PSBoundParameters['extraParameters']
。[PSBoundParametersDictionary]
对象的方法和属性。 $args
param
关键字。 ValueFromRemainingArguments = $true
PositionalBinding
的值。有关其他说明和可能性,请参见about_Functions_Advanced_Parameters和about_Automatic_Variables。
function namedArguments {
[cmdletbinding(PositionalBinding=$false)]
param(
[parameter()][string]$a,
[parameter()][byte]$b,
[parameter()][byte]$c
)
write-host "args is "
$args
write-host "parameters is "
$psboundparameters
}
namedArguments -a "hi" -b 2 -c 3
args is
parameters is
Key Value
--- -----
a hi
b 2
c 3
使用未命名的参数值调用上述函数:
namedArguments -a "test" -b 20 -c 43 "extraparameter"
namedArguments:找不到可以接受的位置参数 参数“额外参数”。在第1行:char:1 + namedArguments -a“测试” -b 20 -c 43“ extraparameter” + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~ + CategoryInfo:InvalidArgument:(:) [namedArguments],ParameterBindingException + FullyQualifiedErrorId:PositionalParameterNotFound,namedArguments
namedArguments "no parameter name"
namedArguments:找不到可以接受的位置参数 参数“无参数名称”。在第1行:char:1 + namedArguments“没有参数名称” + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:InvalidArgument:(:) [namedArguments],ParameterBindingException + FullyQualifiedErrorId:PositionalParameterNotFound,namedArguments
function AllArgumentsWelcome {
[cmdletbinding(PositionalBinding=$false)]
param(
[parameter()][string]$a,
[parameter()][byte]$b,
[parameter()][byte]$c,
[parameter(ValueFromRemainingArguments = $true)][string]$d
)
$PSBoundParameters
if ($PSBoundParameters['d']) { # Checking unnamed parameters
"$($PSBoundParameters['d']) was not assigned to a named parameter!"
}
}
AllArgumentsWelcome -a "test" -b 2 -c 3 "no parameter name"
Key Value
--- -----
a test
b 2
c 3
d no parameter name
no parameter name was not assigned to a named parameter!
[Parameter(Position=0)]
属性
的参数以获得与要求所有参数相似的效果
参数被命名。但是,如果您在一个
函数定义,这将不会产生预期的结果,并且
唯一的未命名参数将被允许。。
答案 1 :(得分:0)
将AdminOfThings' answer和Frode F.的answer to Get ValueFromRemainingArguments as an hashtable放在一起:
[CmdletBinding(PositionalBinding=$false)]
param (
[string][Alias("s")] $sets,
[string][Alias("l")] $location, # /MLF #
[switch][Alias("c")] $conform,
[string][Alias("eM")] $exitMode,
[string][Alias("iM")] $interactionMode,
[string][Alias("lM")] $logMode,
[switch][Alias("tM")] $testMode,
[parameter(ValueFromRemainingArguments)][object[]]$extraParameters = @()
)
#Convert extraparameters to an OrderedDictionary (initially hashtable)
$htvars = [ordered]@{}
$iii = 0 # extraparameters counter
$lastvar = "unnamed_$iii"
$extraparameters | ForEach-Object {
$iii += 1
if($_ -match '^-') {
#New parameter
$lastvar = $_ -replace '^-'
$htvars[$lastvar] = $null
} else {
#Value
$htvars[$lastvar] = $_
$lastvar = "unnamed_$iii"
}
}
#Propagate OrderedDictionary
$htvars
上述解决方案支持以下参数:
示例输出:
PS D:\PShell> .\SO\55042084a.ps1 -a111 -s 555 -abc "ABC" -num 15, 17 'ghi' -Seria "seria" "fifi" -l "llllů" -foo
Name Value
---- -----
a111
abc ABC
num {15, 17}
unnamed_5 ghi
Seria seria
unnamed_8 fifi
foo
PS D:\PShell> .\SO\55042084a.ps1 a111 -s 555 -abc "ABC" -num 15, 17 'ghi' -foo -Seria "seria" "fifi" -l "llllů"
Name Value
---- -----
unnamed_0 a111
abc ABC
num {15, 17}
unnamed_5 ghi
foo
Seria seria
unnamed_9 fifi