【问题标题】:PowerShell : use parameter validation without throwing exceptionPowerShell:使用参数验证而不抛出异常
【发布时间】: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)。好的,对我来说不是问题

  • 如果参数不正确,我无法捕捉到错误(例如显示自定义错误消息)

     

我想在使用错误参数调用脚本时显示自定义错误消息。
是否有可能以及如何在参数错误的情况下捕获异常?

【问题讨论】:

    标签: exception powershell command-line-arguments


    【解决方案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”之前发生这种情况
    猜你喜欢
    • 1970-01-01
    • 2014-07-27
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 2013-04-09
    • 1970-01-01
    相关资源
    最近更新 更多