使用ProcDump捕获程序崩溃信息

当程序崩溃的时候,捕获崩溃信息并进行上报对提升产品质量有很大帮助,它能发现很多在开发和测试阶段发现不了的问题。Windows的WER(Windows Error Reporting)组件在系统级别上提供了捕获崩溃信息的能力,它能够在程序崩溃时生成一个内存转储文件(即dump文件),该文件包含了引发崩溃的异常信息。然而,这个功能仅在Windows Vista SP1及更高的版本中存在,而且它是可配置的,用户可以阻止WER生成dump文件。这意味着我们不能依赖系统来捕获崩溃信息,而是要通过别的途径。

其中一个可选的方案是使用Sysinternals出品的ProcDump。ProcDump是一个命令行工具,它其中的一个功能就是用来捕获程序的崩溃信息。该方案的流程如下:

  • 在程序开始执行的时候,启动ProcDump,并且把自己的进程ID传递给它,让它一直监视该进程。
  • ProcDump一直在后台运行,直到程序正常退出,或者发生崩溃。在后一种情况下,ProcDump会在指定的目录生成dump文件。
  • 程序下一次启动时,发现存在dump文件,进行上报。

可见,这种方案非常简单,只要用正确的参数启动ProcDump即可。假设我们的程序安装在C:\MyApp,进程ID是10032,则启动ProcDump的命令行如下:

1
"C:\MyApp\bin\procdump.exe" -accepteula -e 10032 "C:\MyApp\dump"

启动ProcDump时最好指定procdump.exe的绝对路径,避免进程工作目录改变带来的问题。第一个参数-accepteula表示接受Sysinternals的最终用户许可协议。Sysinternals的工具在首次使用的时候都会弹出最终用户许可协议对话框,使用这个参数可以防止对话框弹出。第二个参数-e表示在进程发生未处理异常(也就是崩溃)时生成dump文件。第四个参数是进程ID,表示让ProcDump监视哪个进程。最后一个参数指定dump文件存放的文件夹路径,要注意的是,这个文件夹必须要预先创建,否则ProcDump会认为这是一个文件路径,并向这个路径写数据,导致异常行为。

最后,程序需要在启动的时候拼接好上述命令行,并调用CreateProcess来启动该命令行。要记得在调用时给dwCreationFlags参数传入CREATE_NO_WINDOW,防止出现控制台窗口。

这个方案实现简单,学习成本低,即使不了解异常相关的机理也可以快速实现崩溃信息收集。但它有一个弊端:ProcDump是以调试器的的身份附加到指定进程上的,进程中发生的调试事件(例如线程的创建和销毁)会导致进程间通信开销,这会稍微影响程序的性能。如果这些性能开销不可接受,则要考虑其它的方案。