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

mna*_*mov 3 powershell

考虑以下脚本

\n\n
#requires -version 2.0\n\n[CmdletBinding()]\nparam\n(\n)\n\n$script:ErrorActionPreference = "Stop"\nSet-StrictMode -Version Latest\nfunction PSScriptRoot { $MyInvocation.ScriptName | Split-Path }\n\nfunction ThrowFunction($i)\n{\n    "ThrowFunction $i"\n    $someNonExistingVariable\n}\n\n@(1, 2, 3) | ForEach-Object -Process { ThrowFunction $_ }\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我们运行它时我们得到

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

正如您所看到的,它在第 18 行报告了问题

\n\n

但实际的问题是在第 #15 行

\n\n

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

\n\n
$script:ErrorActionPreference = "Continue"\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们得到

\n\n
C:\\dev> .\\MyScript.ps1\nThrowFunction 1\nThe variable \'$someNonExistingVariable\' cannot be retrieved because it has not been set.\nAt C:\\dev\\MyScript.ps1:15 char:29\n+     $someNonExistingVariable <<<<\n    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:Token) [], RuntimeException\n    + FullyQualifiedErrorId : VariableIsUndefined\n\nThrowFunction 2\nThe variable \'$someNonExistingVariable\' cannot be retrieved because it has not been set.\nAt C:\\dev\\MyScript.ps1:15 char:29\n+     $someNonExistingVariable <<<<\n    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:Token) [], RuntimeException\n    + FullyQualifiedErrorId : VariableIsUndefined\n\nThrowFunction 3\nThe variable \'$someNonExistingVariable\' cannot be retrieved because it has not been set.\nAt C:\\dev\\MyScript.ps1:15 char:29\n+     $someNonExistingVariable <<<<\n    + CategoryInfo          : InvalidOperation: (someNonExistingVariable:Token) [],     RuntimeException\n    + FullyQualifiedErrorId : VariableIsUndefined\n
Run Code Online (Sandbox Code Playgroud)\n\n

您会看到现在第 15 行已按预期报告。

\n\n

现在的问题是如何获得正确的行并具有 \xe2\x80\x9cStop\xe2\x80\x9d 行为。

\n\n

我尝试了很多方法,但没有一个对我有用。

\n\n

我试过

\n\n
trap { throw $_ }\n\ntrap { $_.InvocationInfo }\n\ntrap { Get-PSCallStack }\n
Run Code Online (Sandbox Code Playgroud)\n\n

但他们都没有找到正确的路线

\n\n

然后我尝试切换

\n\n
$script:ErrorActionPreference = "Continue"\n
Run Code Online (Sandbox Code Playgroud)\n\n

发现只要添加任何trap,就又报错行了。

\n\n

所以我仍在寻找可行的解决方案......

\n

mna*_*mov 5

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

魔法线是

trap { throw $Error[0] }
Run Code Online (Sandbox Code Playgroud)

这个脚本

#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 $_ }
Run Code Online (Sandbox Code Playgroud)

回报

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
Run Code Online (Sandbox Code Playgroud)

伟大的!