如何使用$ ErrorActionPreference =“Stop”获取正确的错误行号

时间:2014-12-25 09:14:33

标签: powershell

考虑以下脚本

#requires -version 2.0

[CmdletBinding()]
param
(
)

$script:ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
function PSScriptRoot { $MyInvocation.ScriptName | Split-Path }

function ThrowFunction($i)
{
    "ThrowFunction $i"
    $someNonExistingVariable
}

@(1, 2, 3) | ForEach-Object -Process { ThrowFunction $_ }

当我们运行它时,我们得到

C:\dev> .\MyScript.ps1
ThrowFunction 1
ForEach-Object : The variable '$someNonExistingVariable' cannot be retrieved because it has not      been set.
At C:\dev\MyScript.ps1:18 char:28
+ @(1, 2, 3) | ForEach-Object <<<<  -Process { ThrowFunction $_ }
    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:Token) [ForEach-Object],     RuntimeException
    + FullyQualifiedErrorId :      VariableIsUndefined,Microsoft.PowerShell.Commands.ForEachObjectCommand

如您所见,报告第18行中的问题

但实际问题在第15行

我发现如果我们改变第8行:

$script:ErrorActionPreference = "Continue"

我们得到了

C:\dev> .\MyScript.ps1
ThrowFunction 1
The variable '$someNonExistingVariable' cannot be retrieved because it has not been set.
At C:\dev\MyScript.ps1:15 char:29
+     $someNonExistingVariable <<<<
    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:Token) [], RuntimeException
    + FullyQualifiedErrorId : VariableIsUndefined

ThrowFunction 2
The variable '$someNonExistingVariable' cannot be retrieved because it has not been set.
At C:\dev\MyScript.ps1:15 char:29
+     $someNonExistingVariable <<<<
    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:Token) [], RuntimeException
    + FullyQualifiedErrorId : VariableIsUndefined

ThrowFunction 3
The variable '$someNonExistingVariable' cannot be retrieved because it has not been set.
At C:\dev\MyScript.ps1:15 char:29
+     $someNonExistingVariable <<<<
    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:Token) [],     RuntimeException
    + FullyQualifiedErrorId : VariableIsUndefined

你看到现在第15行按预期报告。

现在的问题是如何获得正确的行并且有“停止”行为。

我尝试了很多方法,但没有一种适合我。

我试过

trap { throw $_ }

trap { $_.InvocationInfo }

trap { Get-PSCallStack }

但没有一个得到正确的行

然后我尝试切换

$script:ErrorActionPreference = "Continue"

发现只要我添加任何陷阱,就会再次报告错误的行。

所以我仍然在寻找一个有效的解决方案......

3 个答案:

答案 0 :(得分:3)

即使您已将strictmode设置为Latest,$someNonExistingVariable也不会产生终止错误。它只是写入错误流。通过将ErrorActionPreference设置为Stop,您现在可以将Foreach-Object将非终止错误转换为终止错误。这就是错误指示第18行 - Foreach-Object cmdlet的原因。

如果您查看$ Error集合,假设您首先清除(),您会看到两个错误。最新的是$ Error [0] - 这是Foreach-Object抛出的终止错误。 $ Error [1]是尝试访问未定义变量而写入的非终止错误。它有正确的行号 - 15。

您可以像这样访问ScriptStackTrace:

PS C:\> $error[0].errorRecord.ScriptStackTrace
at ThrowFunction, C:\Users\hillr\ErrorLine.ps1: line 15
at <ScriptBlock>, C:\Users\hillr\ErrorLine.ps1: line 18
at <ScriptBlock>, C:\Users\hillr\ErrorLine.ps1: line 18

答案 1 :(得分:3)

感谢@Keith Hill,我找到了一个解决方案

魔术线是

trap { throw $Error[0] }

此脚本

#requires -version 2.0

[CmdletBinding()]
param
(
)

$script:ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
function PSScriptRoot { $MyInvocation.ScriptName | Split-Path }

trap { throw $Error[0] }

function ThrowFunction($i)
{
    "ThrowFunction $i"
    $someNonExistingVariable
}

@(1, 2, 3) | ForEach-Object -Process { ThrowFunction $_ }

返回

C:\Dev> .\MyScript.ps1
ThrowFunction 1
The variable '$someNonExistingVariable' cannot be retrieved because it has not been set.
At C:\Dev\MyScript.ps1:17 char:29
+     $someNonExistingVariable <<<<
    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:Token) [], RuntimeException
    + FullyQualifiedErrorId : VariableIsUndefined

大!

答案 2 :(得分:0)

您可以尝试{} Catch {}:

#requires -version 2.0

[CmdletBinding()]
param
(
)

$script:ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
function PSScriptRoot { $MyInvocation.ScriptName | Split-Path }

function ThrowFunction($i)
{
    "ThrowFunction $i"
    Try {
        $someNonExistingVariable
    }
    Catch { # The variable $_ represents the error that is caught
    Write-Output $_
    }
}

@(1, 2, 3) | ForEach-Object -Process { ThrowFunction $_ }

结果输出给出了正确的行号:

ThrowFunction 1
The variable '$someNonExistingVariable' cannot be retrieved because it has not been set.
At line:16 char:9
+         $someNonExistingVariable
+         ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:String) [], RuntimeException
    + FullyQualifiedErrorId : VariableIsUndefined

ThrowFunction 2
The variable '$someNonExistingVariable' cannot be retrieved because it has not been set.
At line:16 char:9
+         $someNonExistingVariable
+         ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:String) [], RuntimeException
    + FullyQualifiedErrorId : VariableIsUndefined

ThrowFunction 3
The variable '$someNonExistingVariable' cannot be retrieved because it has not been set.
At line:16 char:9
+         $someNonExistingVariable
+         ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:String) [], RuntimeException
    + FullyQualifiedErrorId : VariableIsUndefined