我可以在 PowerShell 中获取详细的异常堆栈跟踪吗?
运行这样的脚本:
1: function foo()
2: {
3: bar
4: }
5:
6: function bar()
7: {
8: throw "test"
9: }
10:
11: foo
我看到
test
At C:\test.ps1:8 char:10
Can I get aDetailed stack trace 相反?
At bar() in C:\test.ps1:8
At foo() in C:\test.ps1:3
At C:\test.ps1:11
Runing such script:
1: function foo()
2: {
3: bar
4: }
5:
6: function bar()
7: {
8: throw "test"
9: }
10:
11: foo
I see
test
At C:\test.ps1:8 char:10
Can I get a detailed stack trace instead?
At bar() in C:\test.ps1:8
At foo() in C:\test.ps1:3
At C:\test.ps1:11
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
PowerShell 团队博客上有一个名为 Resolve-Error 的 功能,它可以帮助您解决问题各种详细信息
请注意,$error 是您在 PSSession 中遇到的所有错误的数组。 此功能将为您提供有关上次遇到的错误的详细信息。
There is a function up on the PowerShell Team blog called Resolve-Error which will get you all kinds of details
Note that $error is an array of all the errors you have encountered in your PSSession. This function will give you details on the last error you encountered.
有自动变量
$StackTrace
但它似乎更具体于内部 PS 细节,而不是实际关心你的脚本,所以这不会有太大帮助。还有
Get-PSCallStack
但不幸的是,一旦遇到异常,它就会消失。 但是,您可以在脚本中的每次抛出之前放置一个Get-PSCallStack
。 这样您就可以在遇到异常之前立即获得堆栈跟踪。我认为可以通过使用 Powershell 的调试和跟踪功能来编写此类功能的脚本,但我怀疑这会很容易。
There is the automatic variable
$StackTrace
but it seems to be a little more specific to internal PS details than actually caring about your script, so that won't be of much help.There is also
Get-PSCallStack
but that's gone as soon as you hit the exception, unfortunately. You could, however, put aGet-PSCallStack
before every throw in your script. That way you get a stack trace immediately before hitting an exception.I think one could script such functionality by using the debugging and tracing features of Powershell but I doubt it'd be easy.
Powershell 3.0 将 ScriptStackTrace 属性添加到 ErrorRecord 对象。 我使用此函数进行错误报告:
Skip 参数允许我将 Write-Callstack 或任意数量的错误处理堆栈帧保留在 Get-PSCallstack 列表之外。
请注意,如果从 catch 块调用,Get-PSCallstack 将错过抛出站点和 catch 块之间的任何帧。 因此,我更喜欢 PS 3.0 方法,尽管每帧的细节较少。
Powershell 3.0 adds a ScriptStackTrace property to the ErrorRecord object. I use this function for error reporting:
The Skip parameter lets me leave Write-Callstack or any number of error-handling stack frames out of the Get-PSCallstack listing.
Note that if called from a catch block, Get-PSCallstack will miss any frames between the throw site and the catch block. Hence I prefer the PS 3.0 method even though we have fewer details per frame.
您无法从脚本的 PowerShell 代码的异常中获取堆栈跟踪,只能从 .NET 对象中获取。 为此,您需要获取 Exception 对象,如下所示:
You can not get a stack trace from exceptions of the PowerShell code of scripts, only from .NET objects. To do that, you will need to get the Exception object like one of these:
我以在这里找到的东西为灵感,创建了一个很好的函数,任何人都可以将其放入他们的代码中。
我就是这样称呼它的:
Write-Host“无法写入日志文件`n$(解决错误)”-ForegroundColor Red
I took what I found here as inspiration and created a nice function anyone can drop into their code.
This is how I call it:
Write-Host "Failed to write to the log file `n$(Resolve-Error)" -ForegroundColor Red
此代码:
将以以下格式回显错误:
This code:
Will echo an error in a following format:
这是一种方法: 跟踪脚本堆栈
其核心是这段代码:
Here's a way: Tracing the script stack
The core of it is this code:
您还可以更改错误对象的默认格式以包含堆栈跟踪。 基本上,通过从 $PSHOME\PowerShellCore.format.ps1xml 复制 System.Management.Automation.ErrorRecord 的块来创建格式文件,并添加您自己的格式文件
添加跟踪的元素。 然后使用 Update-FormatData 加载它。 有关更多详细信息,我刚刚写了一篇关于它的博客文章: https://blogs.msdn.microsoft.com/sergey_babkins_blog/2016/12/28/getting-a-stack-trace-in-powershell/
哦,还有一个事情:这不会自动传播到远程会话中。 这些对象在远程端被格式化为字符串。 对于远程会话中的堆栈跟踪,您必须上传该文件并再次调用 Update-FormatData。
You can also change the default formatting for the error object to include the stack trace. Basically, make your format file by copying the chunk for System.Management.Automation.ErrorRecord from $PSHOME\PowerShellCore.format.ps1xml and add your own
element that adds the trace. Then load it with Update-FormatData. For more details, I've just written a blog post about it: https://blogs.msdn.microsoft.com/sergey_babkins_blog/2016/12/28/getting-a-stack-trace-in-powershell/
Oh, one more thing: this doesn't propagate automatically into the remote sessions. The objects get formatted into strings on the remote side. For stack traces in the remote sessions you'll have to upload this file there and call Update-FormatData there again.
我刚刚想通了。 $_ 是 catch 块中捕获的异常。
I just figured it out. The $_ is the exception caught in the catch block.
也许我误解了一些东西,但我的问题是我没有看到内部异常的 powershell 脚本堆栈跟踪。
最后,我最终在 $Global:Error 中搜索异常的 Error Eecord 对象来检索脚本堆栈跟踪。
用法示例:
输出示例:
Maybe I've misunderstood something, but my issue here is that I've not been seeing powershell script stack traces for inner exceptions.
In the end I ended up searching $Global:Error for an exception's Error Eecord object to retrieve the script stack trace.
Example Usage:
Example output:
在某些情况下,PowerShell 似乎不保留回溯,例如使用
.Invoke()
调用方法或调用函数。 为此,Set-PSDebug -Trace 2
可能会派上用场。 它将打印正在运行的脚本的每个执行行。尝试翻转 (1) 和 (2) 上的 # 并运行
WrapStackTraceLog({ function f{ 1/0 } ; & f }) # 让我们除以零
Branch (1) 捕获异常:
Branch ( 2) 信息更丰富:
但是,您仍然可以通过跟踪分支 (1) 来跟踪您的调用:
There are cases where PowerShell doesn't seem to keep a backtrace, like calling a method or calling a function with
.Invoke()
. For that,Set-PSDebug -Trace 2
may come in handy. It will print every executed line of the running script.Try flipping # on (1) and (2) and running
WrapStackTraceLog({ function f{ 1/0 } ; & f }) # let's divide by zero
Branch (1) exception caught:
Branch (2) is more informative:
But, you can still trace your Invokes with tracing on, branch (1):
偶然发现这个问题正在寻找内置解决方案。 我将采用简单的解决方案。 只需在使用任何 powershell 之前添加跟踪块即可。 这将确保显示调用堆栈。 这样做的缺点是堆栈将在错误消息之前显示。
Stumbled upon this looking for a built in solution. I am going with simple solution. Just add trace block before using any powershell. This will ensure a call stack is shown. Down side of this is the stack will be displayed before the error message.
该线程很旧,但我们实际上可以得到相同的结果:
此外,为了捕获脚本的任何异常,您可以使用它:
工作得很好。
The thread is very old but we can get the same actually with this:
Additionally, to trap any Exception of your script, you can use that:
Worked very well.