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 方法退出而不抛出异常

回滚而不抛出异常?

如何从子方法中退出方法而不抛出异常

IMAPI:如果图像大小超过可用空间,如何获取图像大小而不抛出异常?

JAXB XMLAdapter 方法不抛出异常

我可以在不抛出异常的情况下测试正则表达式在 C# 中是不是有效吗