我有以下PowerShell代码将用户输入验证为路径,如果用户没有输入任何内容,我试图为它们分配默认值。但是,当我运行它时,$filePath
变量不会被赋值任何值。
无论如何,我可以更改此设置,以便在验证过程中为其分配默认值吗?
以下代码:
function validatePath {
Param
(
[ValidateScript({
If ($_ -eq "" -or $_ -eq [String]::Empty) {
$_ = "C:\Install"
$True
}
ElseIf ($_ -match "^([a-z]:\\(?:[-\\w\\.\\d])*)") {
$True
}
Else {
Write-Host "Please enter a valid path,$_ is not a valid path."
Write-debug $_.Exception
}
})]
[string]$filePath = "C:\Install"
)
Process
{
Write-Host "The path is "$filePath
}
}
validatePath -filePath $args[0]
答案 0 :(得分:2)
我认为您可以删除验证脚本,而是在Begin块中执行此操作:
Begin{
If ($filepath -eq "") {
$filepath = "C:\Install"
}
ElseIf ($filepath -notmatch "^([a-z]:\\(?:[-\\w\\.\\d])*)") {
Write-Error "Please enter a valid path,$filepath is not a valid path."
}
}
Process{
答案 1 :(得分:0)
此答案首先讨论正确使用ValidateScript
属性。
之后将讨论无关的默认值问题,然后是参数splatting 的可选部分。
Matt在他对这个问题的评论中提供了很好的指示:
ValidateScript
脚本块应输出仅布尔。
该布尔告诉PowerShell参数值是否被认为是有效的, it 会相应地采取行动。
值得注意的是,脚本块不意味着:
Write-Host
(您不应该使用它来报告错误)。 如果脚本块输出(有效)$False
或,脚本块会抛出异常, PowerShell:
如果脚本块输出$False
,则会得到一般错误消息,其中包含脚本块的文字内容 (不包括封闭内容) {
和}
) - 对于最终用户而言技术性太强。
PowerShell 核心 为ValidateScript
和ValidatePattern
引入了 optional ErrorMessage = "..."
field 属性;例如,
[ValidateScript({ $_ % 2 -eq 0 }, ErrorMessage = "{0} is not an even number.")]
在 Windows Powershell 中,建议抛出异常,并提供用户友好的错误消息**,其中case PowerShell在其错误消息中包含异常文本。
参数的默认值是按设计而不是检查验证脚本 - 您作为函数创建者承担责任默认为有效的值 - 请参阅this blog post。
应用于您的示例:
请注意,我使用'^[a-z]:\\[-\w\d\\]*$'
作为正则表达式,因为这是我认为您实际上要使用的内容。
function validatePath {
Param
(
[ValidateScript({
if ($_ -match '^[a-z]:\\[-.\w\d\\]*$') { return $True }
Throw "'$_' is not a valid local path."
})]
[string] $filePath = "C:\Install"
)
Process
{
"The path is: $filePath"
}
}
现在所有3个调用方案都应按预期工作:
> validatePath # use default value
The path is: C:\Install
> validatePath -filePath C:\MyInstall # valid path
The path is: C:\MyInstall
> validatePath -filePath NotAFullPath # invalid path -> error with custom message
validatePath : Cannot validate argument on parameter 'filePath'.
'NotAFullPath' is not a valid local path.
At line:1 char:24
+ validatePath -filePath NotAFullPath # invalid path
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [validatePath], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,validatePath
此问题与验证无关,并且源于您在$args[0]
调用中传递validatePath
这一事实:
如果脚本本身没有收到任何参数, $args[0]
为$null
,但仍然作为显式值传递< / em> ,因此它通过强制绑定到空字符串来绑定参数$filePath
。
由于传递了显式参数值,因此未使用默认值,$filePath
最终包含空字符串。
由于这是参数绑定在PowerShell中的工作方式,我建议不尝试在函数中解决,而是修复问题关于调用 :
if ([string] $args[0]) { # only true if $args[0] is neither $null nor the empty string
validatePath -filePath $args[0]
} else {
validatePath
}
请注意,通常最好明确声明您的参数,而不是使用$args
。
作为在上述条件中使用两个单独调用的替代方法,请考虑使用parameter splatting,它允许您使用前缀为@
的单个集合变量传递多个参数:
表示多个位置参数的数组。
更常见,更强大,散列表代表多个命名的参数。
这允许您提前动态构建参数集合,并将集合作为一个整体传递给目标命令的单个调用。
在您的情况下,快速而肮脏的解决方法是使用使用所有参数进行展开,即通过$args
(注意{{1} } sigil而不是@
):
$
这将简单地传递所有参数,如果有任何,将脚本传递给validatePath @args
,就好像它们是单独指定的那样;如果没有参数传递给脚本,则不会传递任何内容,并且validatePath
中的-filePath
默认值生效。
参数个人splatting 是另一种选择,是一种将选择参数传递给另一个命令的强大技术:
validatePath
如果使用显式参数声明脚本(使用自己的# Define a hashtable to hold the parameters, if any, to pass through
# to validatePath() via splatting.
$htPassthruParams = @{}
# If the first script argument is neither $null nor the empty string,
# add a hashtable entry for it that will bind to the -filePath parameter.
if ([string] $args[0]) { $htPassthruParams.Add('filePath', $args[0]) }
# Pass the hashtable with `@`, the splatting operator, to validatePath()
validatePath @htPassthruParams
块),可以通过使用自动param(...)
字典来推广该方法确定参数是否绑定 ,这样就无需检查特定值:
$PSBoundParameters