您误解了管道的工作原理。当一系列对象被发送到管道时,每个单独的对象都会在处理下一个对象之前通过整个管道。考虑以下函数:
function First() {
process {
Write-Host "First: $_";
$_
}
}
function Second() {
process {
Write-Host "Second: $_";
}
}
第一个函数输出“First”和管道对象的值,然后传递该对象。第二个仅输出“第二个”和管道对象。现在,当您将数组推送到由这两个函数组成的管道时,您希望看到什么?
实际结果是这样的:
PS C:\Users\Lauri> ,1,2,3 | first | second
First: 1
Second: 1
First: 2
Second: 2
First: 3
Second: 3
现在,有了这些信息,我们可以推断,当管道中的函数或 cmdlet 抛出异常以停止处理时,整个管道将停止。但是我们也可以很容易地验证它。让我们修改First如下:
function First() {
process {
throw New-Object System.Management.Automation.PipelineStoppedException
}
}
然后再次尝试相同的管道:
PS C:\Users\Lauri> ,1,2,3 | first | second
结果是空的,因为第一个对象被传递给“First”的那一刻,它抛出了一个异常,整个管道被中止。
总之,您无法测试处理是否在管道中进一步中止,因为执行将永远不会到达那里。
[编辑] 一个更有趣的花絮:所有函数的 Begin 块首先运行,End 块都在最后运行,所以如果你在管道中更高的 Process 块中抛出异常,所有管道的 Begin 块函数将已经运行:
function First() {
begin {
Write-Host "First begin"
}
process {
throw New-Object System.Management.Automation.PipelineStoppedException
}
end {
Write-Host "First end"
}
}
function Second() {
begin {
Write-Host "Second begin"
}
process {
Write-Host "Second: $_"
}
end {
Write-Host "Second end"
}
}
PS C:\Users\Lauri> ,1,2,3 | first | second
First begin
Second begin
[编辑 2]
另一个可能有趣的结果是,如果发生异常并且您希望管道在此之后继续运行,则需要在捕获它的 catch 块中返回一些内容:
function CauseException {
throw New-Object Exception
}
function First() {
process {
try {
CauseException
} catch {
"Error"
}
}
}
function Second() {
process {
Write-Host "Second: $_"
}
}
PS C:\Users\Lauri> ,1,2,3 | first | second
Second: Error
Second: Error
Second: Error