在某些情况下,ForEach-Object是否会吞下终止错误?

时间:2016-09-14 01:15:12

标签: powershell powershell-v5.0

在使用ForEach-Object调用引发终止错误的脚本时,我在一个非常特殊的情况下看到了一些奇怪的行为。

好像在某些情况下,在-Process脚本块中终止错误不会导致整个脚本执行停止,因为我预期......无论如何都会继续执行。

在这些情况下使用ForEach-Object(或任何cmdlet /高级功能)时,我想知道是否有任何问题。

实施例

以下示例代表了我的期望:

$childScriptPath = '.\childscript.ps1'
Set-Content $childScriptPath -Value @'
    $ErrorActionPreference = 'Stop'

    # normally non-terminating, but should be terminating here due
    # to $ErrorActionPreference = 'Stop'
    Get-Command command_that_does_not_exist 

    # We never get here as expected
    Write-Host 'After Get-Command: should not get here'
'@

"something doesn't matter what" | ForEach-Object {
    & $childScriptPath
}

# Shouldn't get here due to terminating error...works as expected.
Write-Host 'Script should have thrown a terminating error; should not get here'

以下示例不起作用,因为我期待。请注意,唯一的区别是它使用Set-StrictMode后跟未定义变量的引用导致错误而不是使用不存在的命令调用Get-Command

$childScriptPath = '.\childscript.ps1'
Set-Content $childScriptPath -Value @'
    $ErrorActionPreference = 'Stop'
    Set-StrictMode -Version latest

    # normally would silently continue, but should throw a
    # terminating error here due to $ErrorActionPreference = 'Stop'
    # and Set-StrictMode -Version latest
    $undefinedVariable

    # We never get here as expected
    Write-Host 'After undefined variable: should not get here'
'@

"something doesn't matter what" | ForEach-Object {
    & $childScriptPath
}

# Shouldn't get here, but it does!!!
Write-Host 'Script should have thrown a terminating error; should not get here'

如果有人有任何见解,我们将非常感激。

其他信息

实际上,这似乎是cmdlet /高级功能与常规功能之间的行为差​​异,因为如果我们采用"不能按预期工作"上面的示例并使用手动ForEach-Object函数作为常规非高级函数实现,它按预期工作:

$childScriptPath = '.\childscript.ps1'
Set-Content $childScriptPath -Value @'
    $ErrorActionPreference = 'Stop'
    Set-StrictMode -Version latest

    # normally would silently continue, but should throw
    # terminating error here due to $ErrorActionPreference = 'Stop'
    # and Set-StrictMode -Version latest
    $undefinedVariable

    # We never get here as expected
    Write-Host 'After undefined variable: should not get here'
'@

function ForEach-Object2 {
    param (
        [scriptblock]$ScriptBlock
    )

    process {
        & $ScriptBlock
    }
}

"something doesn't matter what" | ForEach-Object2 {
    & $childScriptPath
}

# Shouldn't get here...works as expected.
Write-Host 'Script should have thrown a terminating error; should not get here'

另一方面,如果我们将手动ForEach-Object函数转换为高级函数,我们会回到意外行为:

$childScriptPath = '.\childscript.ps1'
Set-Content $childScriptPath -Value @'
    $ErrorActionPreference = 'Stop'
    Set-StrictMode -Version latest

    # normally would silently continue, but should throw
    # terminating error here due to $ErrorActionPreference = 'Stop'
    # and Set-StrictMode -Version latest
    $undefinedVariable

    # We never get here as expected
    Write-Host 'After undefined variable: should not get here'
'@

function ForEach-Object2 {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline=$true)]        
        [object]$InputObject,

        [Parameter(Position=0)]
        [scriptblock]$ScriptBlock
    )

    process {
        & $ScriptBlock $InputObject
    }
}

"something doesn't matter what" | ForEach-Object2 {
    & $childScriptPath
}

# Shouldn't get here, but it does!!!
Write-Host 'Script should have thrown a terminating error; should not get here'

0 个答案:

没有答案