如何使用 procdump (或类似的)从 .Net 应用程序捕获未处理的异常?
冗长(无聊)的故事
目前,我有一个应用程序仅在一台电脑上导致异常。经过一番挖掘后,我可以用一个小示例应用程序封装问题,但真正的原因仍然隐藏。
由于这台电脑上没有安装 Visual Studio,我们也无法这样做,所以我搜索了另一个解决方案以找到真正的原因。
在第一种方法中,我通过仔细阅读异常消息、与代码进行比较并尝试和尝试来越来越多地精简我的小型应用程序。错误来解决问题的具体问题。但这无助于获取有关所有使用的变量的当前值等的所有信息。
因此,我寻找另一种更好的方法来获取我需要的信息。我已经读过有关转储和迷你转储很长一段时间了,但从来不需要它们,因为直到现在我总是可以在我的开发人员或测试机器上重现用户描述的场景。
但这次似乎只有一台电脑出现问题,不幸的是更换整台机器或安装新的所有东西都没有选择。
为了熟悉如何使用转储,我刚刚编写了一个简单的 C# 测试应用程序,其中包含一个按钮,该按钮除了 抛出 new ArgumentException("Test");
现在我需要创建这样一个按下恶意按钮后,您将生成神奇的转储文件,将其读入 Visual Studio 2008 Professional,并且可以像 VS 中正常运行的应用程序一样查看它,只是“下一步”等不起作用。
据我所知,在特定时间点创建转储的最佳工具是 procdump< /a>,因为您可以定义何时进行一次或多次转储。
所以我只是下载了它并通过调用 procdump -o -e MyApp.exe d:\MyApp.dmp 启动它。它声称MyApp.exe不存在。好吧,是我的错。只需先启动 MyApp,然后启动 procdump。
Procdump 现在正在运行,向我显示它使用的所有选项,并且似乎在等待未处理的异常。没有比这更简单的了,我只需按下我的恶意按钮......而 procdump 中什么也没有发生。
相反,我的应用程序会弹出一个对话框窗口,解释发生了未处理的异常(惊讶,惊讶)以及我想要做什么(详细信息,继续,退出)。但无论我选择什么,procdump 都无法自动创建转储文件。
如果我在对话框显示转储文件时调用 procdump -o MyApp.exe d:\MyApp.dmp
似乎毫无用处,因为在 VS 中打开它后,调用堆栈只是挂起在 ntdll.dll
的某个地方,但在我的代码中却没有(我猜这是等待鼠标点击的对话框的 MessageQueue)。
如果我仔细研究细节,您会发现一些有关如何将未处理的异常委托给 JIT 调试器的信息。但我不需要 JIT 调试器,我想使应用程序崩溃以获取转储文件。
经过这些尝试后,我发现 ClrDump,但这并没有产生任何更好的转储(如果我将其加载到 VS 中并查看调用堆栈)。
考虑到这些信息,您现在(希望)能够为我的 .Net 应用程序提供一个(有效的)解决方案:(
简短的)问题
当一个未处理的异常发生在一个进程中时,我如何能够创建一个转储文件.net 应用程序,我能够加载 MyApp .pdb 文件并查看在什么情况下引发异常?
答案
在 Naveen 和 Lex Li 的帮助下,我可以更深入地了解如何使用故障转储进行调试。现在我只想回顾一下让它工作所需的所有内容:
每当您想获取进程的转储时,您可以在几个工具之间进行选择来完成工作:
- Procdump
- 简单的命令行工具,可以在复杂的场景中创建转储,但它不能捕获.net未处理的异常。
- 调试诊断
- 简单的图形工具,可以在崩溃时(甚至 .net 异常)创建转储,但无法在 Procdump 等高级场景下创建转储。
正如您所看到的,您将获得两个能够在不同情况下创建转储的工具,因此在需要的时间点创建转储时,两者更像是合作伙伴而不是竞争对手。
使用上述工具之一创建转储后,需要分析转储以找出问题的原因。为了进行分析,您可以使用 WinDbg。它是Windows 调试工具的一部分,可以从 Microsoft 获取。不幸的是,WinDbg 的入门门槛相当高,但它确实很强大。也许看看 此博客以更好地了解如何使用此工具。
如果您有 .Net 4 应用程序并使用 Visual Studio 2010,您也可以使用它进行分析。由于有更好的图形用户界面,它更容易使用,但它不具备 WinDbg 的功能。为了获得更好的比较,您应该查看 本文。
最后但并非最不重要的一点是,您还可以在 Visual Studio 2008 中使用 sos.dll。 这里是描述您可以用它做什么的文章。
The long (boring) story
Currently i have an application that leads to an exception on only one pc. After some digging around i could encapsulate the problem with a small sample application, but the true reason is still hiding.
Due to the fact that on this pc is no Visual Studio installed nor we are able to do so i searched for another solution to find the true reason.
In a first approach i stripped down my small application more and more by just carefully reading the exception message, compare to the code and try & error to come to the concrete line of problem. But that wouldn't help to get all the informations about what are the current values of all the used variables etc.
So i searched for another better way to get the informations i need. I already read about Dumps and Minidumps about a long time but never need them, cause till now i could always reproduce the user described scenario on my developer or test machine.
But this time there seems to be only one pc having the problem and unfortunately changing the complete machine or installing everything new there isn't an option.
To get familiar on how to work with dumps i just wrote a simple c# test application, containing a single button which does nothing more than throw new ArgumentException("Test");
Now i need to create such a magical dump file after pushing the malicious button, read it into Visual Studio 2008 Professional and can look at it like a normal running application within VS except that Step next, etc. won't work.
As far as i know the best tool to create a dump at a specific point in time is procdump, due to the possibility you can define when one or multiple dumps are taken.
So i simply downloaded it and started it by calling procdump -o -e MyApp.exe d:\MyApp.dmp
. It claims that MyApp.exe doesn't exists. Okay, my fault. Just start MyApp first and afterwards procdump.
Procdump is running now showing me all its options it uses and seems to await an unhandled exception. Nothing easier than this, i simply push my malicious button ... and nothing happens in procdump.
Instead a dialog window from my application pops up that explains that an unhandled exception occured (surprise, surprise) and what i'd like to do (Details, Continue, Quit). But no matter what i select, procdump isn't able to create a dump file automatically.
If i go and just call procdump -o MyApp.exe d:\MyApp.dmp
when the dialog is showing the dump file seems to be useless, cause after opening it in VS the call stack is just hanging around somewhere in ntdll.dll
but nowhere within my code (i would guess that this is the MessageQueue of the dialog waiting for some mouse clicks).
If i take a closer look into the details you'll find some informations about how to delegate the unhandled exception to a JIT-debugger. But i don't want a JIT-debugger, i'd like to crash the application to get the dump file.
After these tries i found ClrDump, but that didn't produce any better dumps (if i load it into VS and take a look at the call stack).
With these informations taken into account you are now (hopefully) able to provide me with a (working) solution for my .Net application:
The (short) question
How i'm able to create a dump file when an unhandled exception occurs within an .net application, that i'm able to load MyApp .pdb files and see under which circumstances the exception was thrown?
The answer
With the help of Naveen and Lex Li i could get a little more insight on how debugging with crash dumps works. And now i just like to recap all the stuff, that is needed to get it to work:
Whenever you like to get a dump of a process, you can select between several tools to get the job done:
- Procdump
- easy command line tool that can create dumps in complicated scenarios, but it does not work to catch .net unhandled exceptions.
- DebugDiag
- easy graphical tool that can create dumps at crashes (even .net exceptions), but it can't create dumps at advanced scenarios like Procdump.
As you can see you'll get two tools that are capable to create dumps under different circumstances, so both are more partners then rivals in creating a dump at the needed point in time.
After creating a dump with one of the above tool it's time to analyze the dump to find out the reason for the problem. For analyzing you can grab WinDbg. It is part of the Debugging Tools for Windows and can be get from Microsoft. Unfortunately is the entry-barrier of WinDbg quite high but it is really powerful. Maybe take a look into this blog to get a better understanding on how to use this tool.
If you have a .Net 4 application and using Visual Studio 2010 you can also use this for analyzing. It's much easier to use, due to the better graphical user interface, but it doesn't have the power of WinDbg. To get a better comparison, you should take a look into this article.
Last but not least you can also use the sos.dll in Visual Studio 2008. Here is the article describing what you can do with it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
DebugDiag 是基于异常获取内存转储的最简单方法之一。
查找 debugdiag 中的“配置异常对话框”帮助部分,以根据异常生成转储。
下面是一个基于 ArgumentException 生成完整内存转储的示例
DebugDiag is one of the easiest way to get memory dump based on an exception.
Look for "Configure Exception Dialog" help section within debugdiag to generate a dump based on exception.
Below is an example to generate full memory dump based on ArgumentException
DebugDiag 或 WinDbg 都可以。
http://support.microsoft.com/kb/919789
http://www.microsoft.com/whdc/devtools/debugging/default.mspx
DebugDiag or WinDbg is OK.
http://support.microsoft.com/kb/919789
http://www.microsoft.com/whdc/devtools/debugging/default.mspx