PowerShell:使用参数验证而不抛出异常
Posted
技术标签:
【中文标题】PowerShell:使用参数验证而不抛出异常【英文标题】:PowerShell : use parameter validation without throwing exception 【发布时间】:2012-09-10 23:48:04 【问题描述】:我想以这种方式调用 PowerShell 脚本:script.ps1 -path mypath\to\files\ -days 6 -hours 0
要验证命令行参数,我可以手动完成,也可以依赖 param
语法:
Param (
[Parameter(Mandatory=$true )] [string] $path,
[Parameter(Mandatory=$false)] [int] $days,
[Parameter(Mandatory=$false)] [int] $hours
)
如果我使用param
语法:
参数定义必须是脚本的第一行(不包括 cmets)。好的,对我来说不是问题
如果参数不正确,我无法捕捉到错误(例如显示自定义错误消息)
我想在使用错误参数调用脚本时显示自定义错误消息。是否有可能以及如何在参数错误的情况下捕获异常?
【问题讨论】:
【参考方案1】:好吧,不能使用param
AND 来捕获相关异常。
【讨论】:
看来还是可以的,看我的回答。 我的投票是+1,因为我以不同的方式理解了这个问题,并且以这种方式很有趣。也许我应该弃权,这个问题不清楚。您可以尝试编辑它并更好地解释问题。我会再次尝试提供帮助。【参考方案2】:这些示例适用于函数(简单和高级),但同样的想法也适用于带有param
的脚本:
# Simple function.
# Everything not declared in `param` goes to $args.
# If $args is not empty then there are "invalid" parameters or "unexpected" arguments
function test
param (
[string]$path,
[int]$days,
[int]$hours
)
# check $args and throw an error (in here we just write a warning)
if ($args) Write-Warning "Unknown arguments: $args"
或者
# Advanced function.
# For an advanced function we can use an extra argument $args
# with an attribute `[Parameter(ValueFromRemainingArguments=$true)]`
function test
param (
[Parameter(Mandatory=$true )] [string] $path,
[Parameter(Mandatory=$false)] [int] $days,
[Parameter(Mandatory=$false)] [int] $hours,
[Parameter(ValueFromRemainingArguments=$true)] $args
)
# check $args and throw an error (in this test we just write a warning)
if ($args) Write-Warning "Unknown arguments: $args"
以下测试:
# invalid parameter
test -path p -invalid -days 5
# too many arguments
test -path p 5 5 extra
在这两种情况下都会产生相同的输出:
WARNING: Unknown arguments: -invalid
WARNING: Unknown arguments: extra
【讨论】:
这并没有解决问题:如何在参数错误的情况下捕获异常?如果您在强制参数上有错误,脚本就会崩溃,您无法对其采取任何措施。【参考方案3】:一种可能的解决方法是将您的实际功能包装在另一个中。类似于私人/公共关系的东西。示例:
function Example-Private
[CmdletBinding()]
Param
(
[ValidateNotNullOrEmpty()]
[string]$Arg1,
[ValidateNotNullOrEmpty()]
[string]$Arg2
)
# Do what you need
function Example-Public
[CmdletBinding()]
Param
(
[string]$Arg1,
[string]$Arg2
)
try
Example-Private $Arg1 $Arg2
catch
# Display a user-friendly message, save exception into a log file, etc.
如果您正在开发一个模块,您可以在这里查看如何导出您的公共函数并隐藏私有函数:Export Powershell Functions
【讨论】:
这是唯一对我有用的东西。 Powershell v5【参考方案4】:在Begin
块中,您始终可以对参数进行进一步验证,但如果参数错误,我认为您不想继续执行。也就是说,您想抛出一个终止错误。这是一个例子:
param (
[Parameter(Mandatory=$true )] [string] $path,
[Parameter(Mandatory=$false)] [int] $days,
[Parameter(Mandatory=$false)] [int] $hours
)
Begin
if ($hours -lt 0 -or $hours -gt 23)
throw "Hours parameter must be between 0 and 23"
也就是说,我不确定这是否比使用 PowerShell 的内置参数验证功能更好,例如:
param (
[Parameter(Mandatory=$true )] [string] $path,
[Parameter(Mandatory=$false)] [int] $days,
[Parameter(Mandatory=$false)]
[ValidateRange(0,23)]
[int]
$hours
)
【讨论】:
这行不通。它不允许代码在“参数”验证期间捕获任何异常,例如,如果我添加了一个额外的参数。 哪个this
不起作用?第一个示例进行手动验证或第二个示例使用参数验证。我怀疑你的意思是后者没有工作。您是否尝试过第一个示例中的方法 - 在 Begin 块中进行验证?
我测试了第一个例子。我使用 script.ps1 -path xxx -dummy yyy 运行,但未执行“开始”就触发了异常。
-Dummy
不是声明的参数。如果要处理无效参数,请不要使用[Parameter(...)]
。
这是个问题。如果您知道这是不可能的,为什么要给出错误的答案?【参考方案5】:
如果您添加一个带有“ValueFromRemainingArguments”属性的字符串类型的虚拟参数,您可以使用参数语法来做到这一点。 然后您可以在脚本中检查此虚拟参数并采取适当的措施,例如:
Param(
[Parameter(Mandatory=$false)]
[SWITCH]$myparam1,
[Parameter(Mandatory=$false)]
[SWITCH]$myparam2,
[parameter(Mandatory=$false,ValueFromRemainingArguments=$true)]
[STRING]$dummy
)
if ($dummy -eq anythingYouDontLike) throwAMessageOrSomething.
【讨论】:
据我了解,这并没有解决问题,即如果其中一个参数验证失败,如何避免脚本崩溃,甚至在达到“ValueFromRemainingArguments”之前发生这种情况以上是关于PowerShell:使用参数验证而不抛出异常的主要内容,如果未能解决你的问题,请参考以下文章
HttpClient.SendAsync 方法退出而不抛出异常