这是处理管道中错误/异常的正确方法吗?
本文关键字:方法 异常 处理 管道 错误 | 更新日期: 2023-09-27 18:17:09
这是我上一个问题的后续问题,只是想澄清一下。
因为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
块中,我有时可能想要报告哪些项目被成功处理,哪些失败(可能有一个原因)。
在编写PowerShell命令时,您有两个广泛的选项来表示错误:non-terminating
和terminating
错误。
如果命令可以继续,则使用non-terminating
错误。例如,您正在复制1000个文件,第一个文件被锁定。整个行动完全失败是没有意义的。在这种情况下,使用Write-Error
并将错误信息写入该文件的error流并继续复制其他文件就足够了。
在遇到无法继续的错误时使用terminating
错误。例如,如果命令的第一步是建立到远程服务的连接,而该服务没有响应,则无法继续。在终止错误的情况下,您的选项是:A)抛出,B)使用ThrowTerminatingError()或C)让异常逃离命令的实现。这些都是抛出(或不捕捉)异常的变体。
在Write-Error
之后是否使用return
语句取决于您是否想为当前管道对象执行更多代码(可能是清理代码)