这是处理管道中的错误/异常的正确方法吗?

时间:2015-10-10 19:29:31

标签: c# powershell

这是my last question的后续行动,只是要求澄清。

因为ThrowTerminatingError()将终止cmdlet并停止处理管道中的项目。处理管道中“问题”对象的正确方法是什么,但您仍想继续处理其余项目?

我将在这里使用一个非常简单的例子,考虑这个函数:

Function Do-Something
{

    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$True,
        ValueFromPipeline=$True)]
        [int]$value
    )

    process 
    {
        if($value -eq 3)
        {
            // Terminate if $value is 3.
        }
        Write-Output($value)
    }
}

现在假设正在调用此函数......

1..10 | Do-Something

使用throw

if($value -eq 3)
{
    throw '$value was 3'
}

这是输出:

1
2
$value was 3
At C:\Users\Me\Desktop\Untitled1.ps1:51 char:12
+            throw '$value was 3'
+            ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: ($value was 3:String) [], RuntimeException
    + FullyQualifiedErrorId : $value was 3

使用ThrowTerminatingError()

if($value -eq 3)
{
    $PSCmdlet.ThrowTerminatingError((New-Object System.Management.Automation.ErrorRecord -ArgumentList (new-object System.Exception -ArgumentList ('$value was 3')), 'ValueWas3', 'NotSpecified', $value))       
}

生成类似的输出:

1
2
Do-Something : $value was 3
At C:\Users\Me\Desktop\Untitled1.ps1:57 char:9
+ 1..10 | Do-Something
+         ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (3:Int32) [Do-Something], Exception
    + FullyQualifiedErrorId : ValueWas3,Do-Something

但是,如果我使用Write-Error和return语句:

if($value -eq 3)
{
    Write-Error((New-Object System.Management.Automation.ErrorRecord -ArgumentList (new-object System.Exception -ArgumentList ('$value was 3')), 'ValueWas3', 'NotSpecified', $value))
    return
}

所有项目都在处理,在第三个项目上报告错误:

1
2
Do-Something : $value was 3
At C:\Users\Me\Desktop\Untitled1.ps1:58 char:9
+ 1..10 | Do-Something
+         ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException 
   ,Do-Something

4
5
6
7
8
9
10

这是我应该处理流水线对象问题的正确方法,还是应该查看我的函数结构?

基本上,我只是想知道如何处理无法处理的管道中的对象,但我想继续处理剩余的对象。

我想要这样的事情的原因是在函数的end块中我有时可能想要报告哪些项目已成功处理以及哪些项目失败(可能有原因)。

1 个答案:

答案 0 :(得分:2)

编写PowerShell命令时,您有两种广泛的选项来表达错误:non-terminatingterminating错误。

如果命令可以继续,请使用non-terminating错误。例如,您正在复制1000个文件,而第一个文件已被锁定。完全失败整个操作是没有意义的。在这种情况下,使用Write-Error并将错误信息写入该文件的错误流并继续复制其他文件就足够了。

当您遇到无法继续的错误时,请使用terminating错误。例如,如果命令的第一步是建立与远程服务的连接而服务没有响应,则无法继续执行。在终止错误的情况下,您的选项是:A)throw,B)使用ThrowTerminatingError()或C)让异常转义命令的实现。这些是抛出(或不捕获)异常的变体。

BTW是否在return之后使用Write-Error语句取决于您是否要为当前管道对象执行更多代码(可能是清理代码)。