使用WinDBG和PowerShell自动分析大量的小型转储文件
当调试代码中的一个讨厌的问题时,你能得到的最有用的东西之一就是一个小型转储。当你的应用程序在崩溃、挂起或内存开始激增时,你得到了一个很大的提示,可以开始你的探索。虽然有很多工具,比如奇妙的prodump,以及调试器自己来创建小转储,但真正的关键时刻是您必须查看这些小型转储。一个或两个很容易做到,但是如果你有200个呢?在我的工作领域,我调试别人的软件问题,我通常会面对来自客户的数百个转储。尽管我很想仔细打开每个小型垃圾场,并且一遍又一遍地输入相同的命令。
我真正需要的是这样一种方式:“这里有一堆.DMP文件;在所有这些文件中运行这些WinDBG命令。”事实证明,当你结合一点WinDBG知识和一点PowerShell魔法时,完成这项基本任务一点都不难。在开始使用脚本之前,我需要谈谈它是如何工作的。这样你就能更好地理解它的用法。
为了编写WinDBG脚本,以便它在一个文件中执行一组命令,使用$$<命令就可以做到这一点。该命令将读入一个文本文件,并依次执行每一行,就像您在命令区域中键入了它一样。您可以在WinDBG帮助中找到$$<的其他变体,它们提供了稍微不同的功能,但是这个命令对于我来说已经足够了。
如果我想运行!analyze并获取已加载模块的列表,下面的调试脚本文本文件名为,BasicAnalysis.txt,显示这些命令。星号被认为是$$<的注释行。
* Run !analyze !analyze v * Get the list of loaded modules lmv
因此,在WinDBG命令区域中,如果执行$$<BasicAnalysis.txt,则自动运行两个命令。这解决了第一步,但最好是在启动时告诉WinDBG我们希望立即运行一些命令。幸运的是,-c命令行开关告诉WinDBG要做到这一点。所以为了把所有的东西联系在一起,如果我执行下面的命令,它将打开minidump(-z)执行我的文本文件中的命令,并通过Q命令,立即退出。
windbg -z test.dmp -c “$$<BasicAnalysis.txt;Q”
这只是个开始,但有两个问题。首先,我需要捕获命令的输出。第二个原因是WinDBG是一个GUI应用程序,所以如果我想在一堆小型转储中运行一个脚本,我将有许多WinDBG实例在所有地方启动和停止。我可以用同样的方法解决这两个问题:不要使用WinDBG!
解决方法是使用CDB.EXE,WinDBG的控制台专用兄弟,它安装在与WINDBG.EXE文件同一目录中. 因为几乎没有人知道CDB.EXE,CDB.EXE有什么了不起的,它与WinDBG基本上是完全相同的命令窗口,也有完全相同的启动选项,但严格地说是在控制台窗口中。因此,要使用CDB执行相同的命令行,但将输出重定向到文件,请执行以下操作:
cdb -z test.dmp -c “$$<BasicAnalysis.txt;Q” > log.log
您可能想知道为什么我使用输出重定向而不是.logoopen来记录文件。所有这些都是关于捕获最早的输出。如果使用.logopen,则会错过正常输出的前几行,其中包含一些极其重要的信息,例如创建转储的操作系统版本。另外,prodump之类的工具会在命令行中添加注释来创建小型转储。因为那是以前发生的。logopen有机会让你错过它。
现在,您已经了解了如何执行CDB来执行分析工作,下面让我提到一些我在工作中想要的其他需求。第一个是我想要完整的管道支持,所以如果我在一个目录树中有一堆.DMP文件,我可以一次完成它们。其次,我希望每个小型转储文件的日志文件命名为<minidump>-<debuggingscript>.log,并将其放在与minidump相同的目录中。这样可以将所有内容保存在同一个树中,并且可以使用不同的调试脚本执行多次运行,而不会丢失以前运行的的结果。因此有三个参数:
- 文件:要处理的文件或管道集
- DebuggingScript:要针对每个小型转储运行的CDB命令的文本文件
- CdbProgramPath:默认情况下,脚本使用CDB.EXE文件在PATH环境变量中找到,但如果要指定其他CDB.EXE文件,例如在分析x64工作站上的32位.NET转储时,请在此参数中列出完整路径。