这是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
块中我有时可能想要报告哪些项目已成功处理以及哪些项目失败(可能有原因)。
答案 0 :(得分:2)
编写PowerShell命令时,您有两种广泛的选项来表达错误:non-terminating
和terminating
错误。
如果命令可以继续,请使用non-terminating
错误。例如,您正在复制1000个文件,而第一个文件已被锁定。完全失败整个操作是没有意义的。在这种情况下,使用Write-Error
并将错误信息写入该文件的错误流并继续复制其他文件就足够了。
当您遇到无法继续的错误时,请使用terminating
错误。例如,如果命令的第一步是建立与远程服务的连接而服务没有响应,则无法继续执行。在终止错误的情况下,您的选项是:A)throw,B)使用ThrowTerminatingError()或C)让异常转义命令的实现。这些是抛出(或不捕获)异常的变体。
BTW是否在return
之后使用Write-Error
语句取决于您是否要为当前管道对象执行更多代码(可能是清理代码)。