Windows应用程序Crash日志:Dr.Watson与WER归纳总结

从Dr.Watson到WER:Windows崩溃日志的演变

Windows平台上的crash日志机制,经历过一次大换代。早期XP时代靠Dr.Watson,Vista之后换成了Windows Error Reporting(WER)。

说白了,这两个东西干的活差不多——程序崩了,操作系统帮忙记录现场。但细节差别很大。我刚开始做Windows crash分析时,老同事扔给我一个.dmp文件,说“用Dr.Watson看看”。结果我找了半天,发现系统里根本没有Dr.Watson……后来才知道版本不同。

那会儿我意识到:搞crash分析,得先搞清楚你的目标环境用的是哪个机制。不然连日志都找不到。

Dr.Watson:老牌但还在用

触发方式:当应用程序发生未处理异常,Windows会调用drwtsn32.exe进程来生成日志。默认路径在:

C:\Documents and Settings\All Users\Application Data\Microsoft\Dr Watson\

生成的日志包含两部分:drwtsn32.log(文本摘要)和user.dmp(内存转储文件)。

日志里记录了什么?我列一下关键字段:

内容说明
异常类型Access Violation, Divide by Zero 等
发生地址模块名+偏移量,比如 kernel32.dll!0x77e5b3a4
调用栈从当前指令一级级往上回溯
寄存器值EAX, EBX, ECX 等关键寄存器
加载模块列表进程所有DLL及基址
系统信息操作系统版本、补丁号等

限制:Dr.Watson只能针对一个默认调试器,多个程序崩溃时会互相覆盖。而且它的内存转储文件默认是小型转储,信息量有限。我当年帮客户分析一个老工业软件crash,他们的Windows 2000机器上只装了Dr.Watson,崩溃日志里连完整的调用栈都没有,最后我只能靠日志里的地址偏移量去反查符号。

WER:现代Windows的崩溃处理中心

从Windows Vista开始,微软用WER全面替代了Dr.Watson。WER的配置和日志管理统一在注册表和werconv.exe里。日志存储位置:

C:\ProgramData\Microsoft\Windows\WER\ReportQueue\

每个crash生成一个子文件夹,包含:Report.wer(结构化XML)、内存转储(*.dmp)、以及WER上传前后的元数据。

Report.wer长什么样子?我打开过一个实际的:

Version=1
EventType=APPCRASH
EventTime=131234567890123456
Response=Not available
Stage=1
...
Sig[0].Name=Application Name
Sig[0].Value=MyApp.exe
Sig[1].Name=Application Version
Sig[1].Value=1.2.3.4
Sig[2].Name=Fault Module Name
Sig[2].Value=mycore.dll
Sig[3].Name=Fault Offset
Sig[3].Value=0x0001a4b0
...
DynamicSig[1].Name=OS Version
DynamicSig[1].Value=10.0.19041.2.0.0.256.48
... 

这比Dr.Watson的日志清晰多了。每个字段都有唯一签名,WER还会把这些签名上传到微软服务器做聚合分析。大型软件公司利用WER后台能看到一个Bug影响了多少用户。

实战:我如何快速定位Dr.Watson和WER日志

  1. 先确认操作系统版本:用ver命令或winver。XP及以下看Dr.Watson,Vista及以上看WER。
  2. 检查日志是否存在:如果用户远程发来“工具崩溃了但没任何提示”,我会让他在崩溃后马上打开事件查看器(Event Viewer),看Windows日志 → 应用程序里有没有WER错误事件。
  3. 提取转储文件:对于WER,直接去ReportQueue下按时间排序找到最近的*.dmp。Dr.Watson的user.dmp默认只有一个,容易被覆盖——这是个大坑。
  4. 用WinDbg加载:设置好符号路径,执行!analyze -v查看自动化分析结果。

关键对比总结

特性Dr.WatsonWER
首次引入Windows 95Windows Vista
日志文件格式纯文本+二进制dmpXML结构化+转储
支持多实例否(单实例)是(队列机制)
自动上传否是(可配置)
调用栈完整性较差(依赖框架帧)较好(含Shadow Stack)
适用于企业调试个体分析大规模聚合分析

避坑指南:为什么我看不到完整的crash日志?

我曾经帮一个游戏公司追查线上崩溃,结果发现用户反馈的日志文件只有几KB。打开一看,全是0x00000000的地址。查了半天,原来是WER在生成转储时把Minidump类型设为MiniDumpNormal,只记录了线程信息,没有堆内存。修改HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\DumpType为0(满转储)即可获取完整信息。

注意事项

  • Dr.Watson在Windows 10中已被彻底移除,但部分旧版Windows Server仍通过兼容模式保留。
  • WER默认不生成完整转储,需要手动开启:HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps。
  • 企业环境可通过组策略禁止WER上传敏感数据,但仍然保留本地日志。
  • 跨平台分析时,注意WER的Report.wer文件包含的应用程序签名和异常签名,这两组签名组合唯一标识一个bug类型。

核心知识结构

下面的流程图展示了一次应用程序崩溃后,Dr.Watson与WER两种机制分别如何产生日志,以及它们之间的关键差异。

Dr.Watson vs WER 崩溃日志生成流程 应用程序崩溃 OS版本 Dr.Watson 捕获 WER 捕获 生成日志:drwtsn32.log + user.dmp 生成日志:Report.wer + *.dmp 使用WinDbg分析转储文件

我的个人习惯:收到一个crash日志后,我第一步不是开WinDbg,而是先看Report.wer里的Fault Offset和Fault Module。如果偏移量落在已知的DLL里,我会直接去查那个DLL的版本和符号。这招在快速排查“升级后立刻崩溃”的问题时特别好使。比如有一次用户把驱动DLL从1.0升级到2.0,crash偏移量在0x1a4b0,我查了旧版符号发现那里是一个已废弃的函数,新版直接删掉了,导致调用空指针。

总结:选哪个?

如果你还在维护XP/2003系统,只能用Dr.Watson。但哪怕能升级,我强烈建议迁移到WER。理由很实在:

  • WER的日志结构更规整,自动化解析脚本好写
  • 支持多实例缓存,不会互相覆盖
  • 企业级聚合分析能力
  • 转储类型可配置,满足不同分析深度

最后说一个我很早以前踩过的坑:在Windows 10上以管理员模式运行的程序,WER有时不会写入ReportQueue,而是写到ReportArchive里。如果你按默认路径找不到日志,记得检查C:\ProgramData\Microsoft\Windows\WER\ReportArchive\。嗯,这玩意儿文档里可没写那么细。