Windows 崩溃转储收集入门 - WER/ProcDump/WinDbg

· 更新日期: · · Windows开发, 故障排查, 崩溃转储, WER, ProcDump, WinDbg

更新记录(2 条,最后更新 2026年09月03日)

本文的修改记录。已保存的更新前版本,可通过带有 DOI 的永久链接阅读。

本文此前是日文原文的节译,缺少大量章节、表格、Mermaid 图、图题、脚注与 FAQ。现已改写为日文原文的完整译文,技术主张与日文版一致,并补上了此前缺失的图与表,同时统一了全篇的术语译法。 查看更新前的版本 (DOI: 10.5281/zenodo.22276843)
补充了日文原文中已有的咨询引导(consultation_services)。正文内容没有改动。 查看更新前的版本 (DOI: 10.5281/zenodo.21615487)
首次发布
引用本文(DOI: 10.5281/zenodo.21615486)

本文保存于 Zenodo。以下同时提供始终指向最新版本的 DOI,以及固定于您正在阅读版本的 DOI。

小村 豪(2026)。《Windows 崩溃转储收集入门 - WER/ProcDump/WinDbg》。小村软件有限公司。https://doi.org/10.5281/zenodo.21615486 https://comcomponent.com/zh-CN/blog/2026/03/16/008-windows-app-crash-dump-collection-introduction/

DOI(最新版本)
10.5281/zenodo.21615486
DOI(此版本)
10.5281/zenodo.22282006

在 Windows 应用上,一旦出现“偶尔才崩溃”的症状,只靠日志追不下去的场面相当多。

尤其棘手的是下面这些情况。

  • 只在客户环境才发生
  • 拿到了异常消息,但缺少调用方的上下文
  • 不只是 C# / .NET 的托管侧,还牵涉 COM、P/Invoke、原生 DLL、厂商 SDK
  • 只有在长时间运行之后才崩溃

这种时候管用的就是崩溃转储。只要把崩溃时刻的进程状态落到文件里,事后就能读到异常代码、崩溃线程的堆栈、当时加载的模块,以及部分或全部内存。

在 Windows 上,先用 WER 的 LocalDumps,需要时再加上 Sysinternals 的 ProcDump,想进一步自己掌控时才用 MiniDumpWriteDump——按这个顺序考虑最容易理解。本文以 Windows 桌面应用、常驻应用、Windows 服务、设备联动工具等为前提,整理崩溃转储收集的第一步。

考虑收集手段的顺序Windows 的崩溃转储收集,按先用 WER 的 LocalDumps、需要时用 Sysinternals 的 ProcDump、想进一步掌控时用 MiniDumpWriteDump 的顺序来考虑最容易理解,本图说明这一点。先用WER LocalDumps需要时加上ProcDump想进一步掌控就用MiniDumpWriteDump

图1:从标准功能开始,只在不够的地方逐步添加工具的顺序。

本文反复出现的术语

先把它们简短地固定下来。这里含糊不清的话,后面几章都会变得模糊。

术语 含义
PDB 构建时生成的调试信息文件。它是把地址还原成函数名和行号的对照表
符号 地址与名称之间的对应信息,由 PDB 或符号服务器提供。没有它,调用堆栈就只是一串地址
first chance exception 异常刚发生、应用的异常处理程序还没处理的阶段。只要应用 catch 住,处理就会照常继续
second chance exception 应用没能处理掉,作为未处理异常让进程走向终止的阶段。平时说“崩溃了”指的就是这个
postmortem debugger 崩溃时由操作系统自动启动的调试器。它是作为整台机器的崩溃时行为注册的
小型转储 / 完整转储 转储中包含的内存量不同。第 7 章会讲

1. 先说结论

先把最需要掌握的几点列出来。

  • 首先 按应用单独配置 WER LocalDumps 最稳妥。不用额外工具,就能在崩溃后把转储留在本地。
  • 复现率低的现场排查,或者想连 first chance exception / hang 一起看时,就用 ProcDump。
  • 自研收集放到最后再考虑 正好合适。等真正需要时再评估 MiniDumpWriteDump 就够了。
  • 和转储同等重要的是 PDB 与发布二进制文件的保存。只有转储而没有符号,能读到的信息会大幅减少。
  • 完整转储很强,但体积和混入机密信息的风险同样很大。保存位置、保留份数、访问权限、共享流程要先定好。

入门阶段推荐的配置,大致会落在下面这些地方。

环境 起步配置
开发机 / 验证机 按应用单独配置 WER LocalDumps,先用 DumpType=2 取完整转储
客户环境 / 现场机 看容量与机密要求选 DumpType=1 或 2。只在必要时追加 ProcDump
长时间运行或 hang 排查 在 WER 之外再考虑 ProcDump 的 -h 或 -e 1
想连自定义 UI 和附带日志一起收 以独立进程为前提,用 MiniDumpWriteDump 做自研收集

总之就是 先 WER,再 ProcDump,最后自研。从反方向开始,设计通常都会变重。

图中实线表示始终成立的关系,虚线表示带条件的关系(成立条件写在详情页各关系的说明中)。关系的完整列表(共 21 条,附依据与确信度)以及主要概念的定义,汇总在知识地图详情页(日文)。数据:JSON-LD / Turtle

2. 崩溃转储能告诉我们什么

崩溃转储是“那一刻的快照”。与其说是监控录像,不如说更接近事故现场的静止画面。

因此,下面这类信息相当容易拿到。

  • 是以哪个异常代码崩溃的
  • 是哪条线程崩溃的
  • 那一刻的调用堆栈
  • 当时加载的模块
  • 根据包含了多少内存,还能看到堆上的状态和对象的内容

另一方面,也有一些信息光靠转储容易不够。

  • 走到这一步的时间线
  • 从几小时前就开始的增长趋势
  • 与通信或设备之间的外部状态
  • 崩溃前的输入和业务上下文

所以实际工作中,不要想着只靠转储把事情做完,而要与日志和 heartbeat 组合起来,这是基本原则。

转储与日志的组合崩溃转储像事故现场的静止画面一样擅长记录那一刻的状态,而走到这一步的时间线和外部状态由日志或 heartbeat 补足,因此把两者组合起来使用是基本做法,本图说明这一点。崩溃转储〔瞬间的静止画面〕组合起来排查日志或heartbeat〔时间线〕擅长异常代码和堆栈擅长走到这一步的经过

图2:静止画面式的转储和时间线式的日志,擅长的领域分得很清楚。

3. 收集方法全景

在 Windows 应用的转储收集中,入门阶段要掌握的方法有下面 4 种。

方法 适合的场景 优势 注意事项
WER LocalDumps 想先常设起来的崩溃收集 Windows 自带,容易按应用单独配置 基本面向崩溃。hang 和细致的条件分支较弱
ProcDump 复现率低的排查、hang、first chance exception 触发条件多,容易投入现场 会变成外部工具的运维
任务管理器的创建转储 想手动抓取当前状态 用 GUI 当场就能抓 不是自动收集
MiniDumpWriteDump 想做自研的诊断功能 容易把附带日志和自定义元数据打包在一起 实现得粗糙反而会把自己搞坏

对新手来说最重要的是,比起“用什么抓”,先决定“在什么条件下”“抓到哪里”“抓多大”。

比工具更该先决定的事崩溃转储收集要先决定在什么条件下抓、抓到哪里、抓多大,然后再进入用什么抓这一工具选择,这一点很重要,本图说明这一点。在什么条件下抓先决定的3点输出到哪里抓多大然后再选工具

图3:先定好条件、输出位置和大小,选工具就不会犹豫。

4. 起步首推 WER LocalDumps

4.1 最先要看的注册表值

Windows Error Reporting (WER) 提供了 LocalDumps,可以在崩溃后把用户模式转储保存到本地。因为不必分发额外工具,作为第一步相当好用。

基本的键在这里。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps

也可以在这里放全局配置,但实际工作中集中到 按应用划分的子键 上更好管理。

LocalDumps 配置的放置位置虽然也可以把全局配置直接放在 LocalDumps 键下,但实际工作中集中到 MyApp.exe 这样按应用划分的子键上更好管理,本图说明这一点。LocalDumps键直接放在键下的全局配置按应用划分的子键实务中这边更好管理

图4:同样是这个键,集中到应用名的子键上就能缩小影响范围。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe

最先要看的值有 3 个。

值 含义 起步建议
DumpFolder 转储的输出位置 单独划一个专用文件夹
DumpCount 保留份数 从 5~10 左右开始
DumpType 0=自定义、1=小型、2=完整 一开始用 2,容量吃紧就用 1

4.2 按应用单独配置的示例

举例来说,如果想让 MyApp.exe 把完整转储最多保留 10 份到 C:\CrashDumps\MyApp,可以先这样配置。

reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpFolder /t REG_EXPAND_SZ /d "C:\CrashDumps\MyApp" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpCount /t REG_DWORD /d 10 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpType /t REG_DWORD /d 2 /f

这个示例有 4 个要点。

  • 限定到 MyApp.exe,而不是全局
  • 把输出位置分离到专用文件夹
  • 起步先取完整转储
  • 把保留份数限制为 10

4.3 确认真的抓到了

配置好之后,与其在生产环境等待自然发生,不如 先在验证环境完整地抓一次,这样更安全。

要确认的是这 4 点。

  1. 预期的文件夹里会不会出现 .dmp
  2. 文件大小是否符合运维预期
  3. 能不能用 WinDbg 打开
  4. 事件查看器的 Application 日志里能不能看到 crash
配置后的验证流程配置好之后,在生产环境等待自然发生之前必须先在验证环境完整抓一次,确认文件夹里是否出现转储、大小是否符合预期、能否用 WinDbg 打开、事件查看器里能否看到 crash,本图说明这一流程。加入配置在验证环境里故意让它崩溃确认转储是否产生及其大小确认能否用WinDbg打开确认事件查看器的日志

图5:在等待生产环境自然发生之前,先在验证环境完整抓一次。

4.4 用于故意崩溃的最小代码

虽说要“完整抓一次”,可要是干等真实崩溃,验证就无从谈起。为验证准备一个 只负责故意崩溃的小 EXE,会快得多。

如果是 .NET,只抛出未处理异常的控制台应用就够了。.NET 的托管未处理异常会终止进程,所以直接就成为 WER 的对象。

// CrashTest.csproj: <TargetFramework>net8.0</TargetFramework>
using System;
using System.Threading;

internal static class Program
{
    private static void Main()
    {
        Console.WriteLine($"PID={Environment.ProcessId} / 3 秒后崩溃。");
        Thread.Sleep(3000);

        throw new InvalidOperationException("intentional crash for dump collection test");
    }
}

如果想验证原生侧,触发访问冲突 (0xC0000005) 更贴近实际。为了不被优化掉,要加上 volatile。

// crash_test.cpp / C++17 / MSVC
int main()
{
    volatile int* p = nullptr;
    *p = 1;  // 这里会发生 STATUS_ACCESS_VIOLATION
    return 0;
}

这里只有一个地方特别容易踩空。 LocalDumps 的子键名,必须与当前要崩溃的 EXE 文件名一致。 只建了 MyApp.exe 的键却去让 CrashTest.exe 崩溃,当然不会产生转储。验证时,要么临时建一个 CrashTest.exe 的键,要么用全局配置那边来试。

子键名一致这个陷阱LocalDumps 的子键名如果与当前要崩溃的 EXE 文件名不一致就不会产生转储,因此验证时要么临时创建 CrashTest.exe 的键,要么用全局配置那边来试,本图说明这一点。只建MyApp.exe的键让CrashTest.exe崩溃不会产生转储键名要与崩溃的EXE名一致

图6:子键名与EXE名不一致,是验证落空的经典陷阱。

Sysinternals 的 NotMyFault 也经常被当作“故意让它崩溃”的工具提起,但它是让 Windows 系统本身 crash / hang 从而 生成蓝屏转储 用的,还需要管理员权限。要验证用户模式应用的 LocalDumps,还是上面那种自己写的小 EXE 更安全可靠。

5. 什么时候用 ProcDump

WER 就够用的情况很多,但也有 ProcDump 更方便的场景。

  • 不想在注册表里常设配置
  • 只想监视已经在运行的进程
  • 只想从下次启动开始监视
  • 想看 first chance exception
  • 想抓 hang
  • 想按性能计数器或其他条件来抓

5.1 常用选项

只挑入门阶段常用的来看,ProcDump 记住下面这些就相当够打了。

选项 含义
-ma 完整转储
-mp MiniPlus 转储
-mc <Mask> 自定义转储。用十六进制指定 MINIDUMP_TYPE 的位掩码
-e 在未处理异常时抓转储
-e 1 在 first chance / second chance 异常时抓转储
-h 在窗口挂起时抓转储
-w 等待目标进程启动
-x 启动目标进程并监视
-n 最大转储份数
-accepteula 自动接受首次的 EULA 确认

5.2 代表性的命令示例

对已在运行的进程,在未处理异常时抓完整转储

procdump -accepteula -ma -e 1234 C:\CrashDumps\MyApp

等待下次启动,在未处理异常时抓完整转储

procdump -accepteula -ma -e -w MyApp.exe C:\CrashDumps\MyApp

自己启动进程并直接监视

procdump -accepteula -ma -e -x C:\CrashDumps\MyApp MyApp.exe

连 first chance exception 也想抓

procdump -accepteula -ma -n 3 -e 1 MyApp.exe C:\CrashDumps\MyApp

想抓挂起

procdump -accepteula -h MyApp.exe C:\CrashDumps\MyApp

5.3 为什么不把 -i 当成第一步

ProcDump 还有一种用法,是用 -i 把它注册成 postmortem debugger。这个用法很强,但因为 会介入整台机器的崩溃时行为,作为入门阶段的第一步稍微重了些。

所以一开始从 WER 的按应用单独配置,或者 ProcDump 的 -w / -x / 指定 PID 入手更好掌握。

不把-i当成第一步的理由ProcDump 的 -i 是注册为 postmortem debugger 的强力用法,但会介入整台机器的崩溃时行为,因此入门阶段从 WER 的按应用单独配置或 ProcDump 的 -w、-x、指定 PID 入手更好掌握,本图说明这一点。用ProcDump的-i注册介入整台机器的行为作为入门第一步太重一开始用按应用划分的配置WER的按应用单独配置ProcDump的-w、-x或指定PID

图7:从影响范围能收敛在应用级别的入口开始。

6. 自研收集使用 MiniDumpWriteDump 时的思路

适合自研收集的,例如下面这些场景。

  • 想在 UI 上放一个“保存诊断信息”的按钮
  • 想把日志、配置、trace ID 与转储捆在一起
  • 想把相关的子进程和辅助进程也一并打包
  • 想在上传前加入自定义的脱敏或压缩

这里的核心 API 是 MiniDumpWriteDump。

不过它有点脾气。入门阶段特别不想弄错的是下面 2 点。

  1. 如果可以,从与转储目标不同的进程里调用
  2. DbgHelp 系列要按 single-threaded 的前提来使用
自研收集中不想弄错的2点用 MiniDumpWriteDump 做自研收集时,要守住如果可以就从与转储目标不同的进程里调用、以及把 DbgHelp 系列按 single-threaded 的前提来使用这 2 点,本图说明这一点。用MiniDumpWriteDump自研收集从另一个进程调用DbgHelp以single-threaded为前提实现得粗糙反而会坏事

图8:自研收集的脾气,集中在调用位置和线程这2点上。

7. 小型转储 / 完整转储 / 中等大小该怎么选

在这里犹豫的人相当多。下面把实务中的选法列成表。

种类 适合的场景 优点 注意事项
小型转储 想先广泛铺开、想让共享更轻 体积小,容易传输 还原状态的深度较弱
完整转储 想优先查清原因,怀疑原生边界或堆有问题 能拿到的信息多 体积大,混入机密信息的风险高
MiniPlus / Custom 小型不够、完整又太重 能取得平衡 需要调参的知识

给新手的建议相当简单。

  • 开发机 / 验证机就用完整转储
  • 客户环境按运维条件在小型和完整之间选
  • 怀疑内存损坏、原生 DLL、COM、P/Invoke、长时间运行后的状态异常,就偏向完整
转储种类的起步选法开发机或验证机用完整转储,客户环境按运维条件在小型和完整之间选,怀疑内存损坏、原生边界或长时间运行后的状态异常就偏向完整,本图说明这一选法。开发机 / 验证机客户环境疑似损坏或原生边界在哪种环境抓完整转储按运维条件选小型或完整

图9:拿不定主意就按环境决定,可疑程度越浓就越往完整那边靠。

7.1 MiniPlus / Custom 实际上该怎么指定

表格里只有第 3 行的指定方法稍微难懂一些,这里补充说明。

在 WER LocalDumps 的情况下,先把 DumpType 设为 0(自定义),再在 CustomDumpFlags 里填入 MINIDUMP_TYPE 的位组合。CustomDumpFlags 是只在 DumpType=0 时才会使用的值,默认为 0x00000121(MiniDumpWithDataSegs MiniDumpWithUnloadedModules MiniDumpWithProcessThreadData 的组合)。

reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpType /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v CustomDumpFlags /t REG_DWORD /d 0x121 /f

在 ProcDump 的情况下,-mp 是 MiniPlus,-mc <Mask> 是自定义。

procdump -accepteula -mp -e MyApp.exe C:\CrashDumps\MyApp

MiniPlus 虽然名字带个 Mini,内容却相当靠近完整转储。按文档所述,它包含 全部 private 内存,以及全部可读写的 image / mapped 内存,在此基础上 仅排除超过 512MB 的那块最大的 private 区域 来压缩体积。结果就定位成“详细程度接近完整转储,体积却只有完整转储的 10%~75%”。

不过有 2 点需要注意。

  • 由于调试上的限制,CLR 进程即使指定 -mp,也会按完整转储 (-ma) 采集。 在 .NET 应用上指望 MiniPlus 减小体积,多半会落空
  • 如果压缩体积的动机是“想减少机密信息的混入”,那么与其用 MiniPlus,不如直接从小型转储那边考虑更自然
MiniPlus的定位与限制MiniPlus 包含全部 private 内存以及可读写的 image、mapped 内存,仅排除超过 512MB 的那块最大 private 区域,从而收敛到完整转储的一成到七成多的体积,但在 CLR 进程上即使指定 -mp 也会按完整转储采集,本图说明这一点。CLR进程的情况用MiniPlus采集private内存几乎全部包含仅排除巨大的private区域比完整转储小却同样详细会按完整转储采集

图10:MiniPlus的内容靠近完整转储,在.NET应用上压缩体积不起作用。

8. 运维上要先定好的事

转储收集在运维层面栽跟头的情况,比在实现层面多得多。下面列出希望先定好的事项。

8.1 PDB 与二进制文件要怎么留存

这一条最重要。

  • 已发布的 EXE / DLL 的准确版本
  • 与该版本对应的 PDB
  • 是由哪个 commit / 哪条构建流水线产出的
  • 安装包与发布物的版本信息

8.2 输出到哪里、留几份

完整转储会相当大。输出位置和保留方针从一开始就定好更安全。

  • 不要一直放在系统盘根目录
  • 分离到专用文件夹
  • 用 DumpCount 或 -n 设上限
  • 把长期保存与临时保存分开

8.3 谁可以查看

完整转储里可能混入机密信息或个人信息。

  • 明文配置
  • 连接字符串
  • 令牌或凭据
  • 崩溃前正在处理的业务数据
  • 文件路径和用户名

所以,在设计“怎么抓”的同时,也必须定好“谁可以接触”。

运维上要先定好的3点崩溃转储收集在运维层面比在实现层面更容易栽跟头,因此要先定好 PDB 与二进制文件的保存、输出位置与保留份数、以及谁可以查看这一访问方针,本图说明这一点。PDB与二进制文件的保存先定好输出位置与保留份数谁可以查看比起实现更容易在运维上栽跟头

图11:转储收集的失败,多半来自运维约定的缺失。

9. 抓到之后的最短分析路线

抓到转储之后,最先要做的事其实相当朴素。

9.1 安装 WinDbg

现在的 WinDbg 通过 Microsoft Store 或 winget 就很容易安装。

winget install Microsoft.WinDbg

9.2 打开转储

windbg -z C:\CrashDumps\MyApp\MyApp_YYMMDD_HHMMSS.dmp

这里的文件名是 ProcDump 生成的默认名称。ProcDump 的默认文件名是 PROCESSNAME_YYMMDD_HHMMSS.dmp,可以把 PROCESSNAME / PID / EXCEPTIONCODE / YYMMDD / HHMMSS 当作替换说明符使用。

另一方面,WER LocalDumps 会用与 ProcDump 不同的命名来生成文件。命名规则在 Microsoft Learn 上并没有写明,所以与其猜名字去找,不如按修改时间顺序查看输出文件夹更可靠。

dir /o-d "C:\CrashDumps\MyApp\*.dmp"

没有配置 DumpFolder 时,默认的输出位置是 %LOCALAPPDATA%\CrashDumps。不过 服务的崩溃会输出到各个运行账户的配置文件文件夹。System 服务是 %WINDIR%\System32\Config\SystemProfile,Network Service / Local Service 则在 %WINDIR%\ServiceProfiles 之下。觉得“怎么没有转储”时,先怀疑这里。

找不到转储时该去哪里找没有配置 DumpFolder 时的默认位置是 LOCALAPPDATA 下的 CrashDumps,而服务的崩溃会输出到各个运行账户的配置文件文件夹,因此觉得没有产生转储时要先怀疑那里,本图说明这一点。普通应用服务找不到转储当时以什么形式运行LOCALAPPDATA下的CrashDumps运行账户的配置文件目录下SystemProfile或ServiceProfiles

图12:默认输出位置因账户而异,所以要从找的地方开始怀疑。

9.3 配置符号

先让 Microsoft 公开符号处于可用状态,之后再加上自己 PDB 的位置。

.symfix C:\Symbols\Microsoft
.sympath+ C:\Symbols\MyApp
.reload

9.4 先看自动分析

!analyze -v

在此基础上,

  • 是哪个异常代码
  • faulting module 是什么
  • 自己的代码在堆栈上露出到什么程度
  • 除异常线程之外,有没有可疑的等待或卡顿

按这个顺序依次查看。

抓到之后的最短分析路线安装 WinDbg、打开转储、配置 Microsoft 公开符号与自己的 PDB,先看 analyze -v 的自动分析,再依次确认异常代码、faulting module、自己代码的可见程度、其他线程的卡顿,本图说明这一流程。安装WinDbg打开转储配置符号与PDB先看自动分析依次读异常代码与堆栈

图13:打开、接通符号、从自动分析开始读,这是最短路线。

10. 常见的坑

10.1 转储抓到了,但没有 PDB

这种情况相当多。转储收集是成功了,但可读的材料不足。 在做收集配置的同一时间,把 PDB 的保存设计也一起做进去 会更好。

10.2 没有查看 DumpFolder 的 ACL

在服务或做了权限隔离的进程上,这里很容易落空。 先确认“那个进程是不是真的能写进去”。Microsoft Learn 也写明,如果使用默认以外的路径,就要确认“ACL 允许崩溃的进程写入”。

当前的 ACL 可以用 icacls 查看。

icacls C:\CrashDumps\MyApp

如果写入权限不足,就给运行账户加上 M(修改)。转储文件夹下面的文件也需要同样的权限,所以要加上 (OI) 和 (CI) 让它继承。

rem 示例:以 Network Service 运行的服务
icacls C:\CrashDumps\MyApp /grant "NT AUTHORITY\NETWORK SERVICE:(OI)(CI)M"

(OI) 指定把 ACE 继承到下面的文件,(CI) 指定继承到下面的文件夹。继承的范围会直接变成“谁能读到转储”,所以在授予之前,请先确认它与 8.3 里定下的方针有没有冲突。

DumpFolder的ACL确认流程在服务或做了权限隔离的进程上写入容易落空,因此要用 icacls 查看当前的 ACL,不够就给运行账户授予带继承的修改权限,再把继承范围与查看方针对照,本图说明这一流程。不能写能写用icacls查看当前的ACL运行账户能否写入授予带继承的修改权限就这样运维继承范围要与查看方针对照

图14:能否写入的确认与谁能读取的确认,在同一个地方一起做完。

10.3 持续把完整转储写到生产机的系统盘

这是容量方面的经典问题。 保留份数限制与输出位置分离 要从一开始就加上。

10.4 想只用 WER 把 hang 也全包了

WER LocalDumps 首先是对 crash 有效。 有些场景下,hang 和 first chance exception 更适合交给 ProcDump。

10.5 一直开着 -e 1,结果被异常淹没

first chance exception 很好用,但数量本来就多。 设置数量上限、只开短时间、限定目标 才现实。

11. 总结

对复现率低的故障来说,崩溃转储是相当有力的观测点。特别是 Windows 应用牵涉到 COM、P/Invoke、原生 DLL、长时间运行时,从一开始就定好“崩溃之后会留下什么”很有价值。

推荐的顺序很简单。

  1. 先按应用单独加上 WER LocalDumps
  2. 需要时再加上 ProcDump
  3. 想进一步掌控时,以独立进程为前提使用 MiniDumpWriteDump

按这个顺序推进,就不容易大幅走偏。

12. 参考资料

共享相同标签的最新文章。可以围绕相近的主题进一步加深理解。

与本文相近的主题页面。以本文为起点,可以进一步了解相关服务和其他文章。

本文与以下服务页面相关联,欢迎从最接近的入口查看。

故障调查 & 根本原因分析

把崩溃转储、日志、复现条件组合起来逐步缩小范围的思路,与故障调查、原因分析这一主题非常契合。尤其是只在现场发生的崩溃、或长时间运行之后才出现的故障,观测点的设计本身就很关键。

技术咨询 & 设计评审

如果希望连同生产环境要采集什么、转储与日志如何融入设计、访问权限与保存方针一起梳理清楚,那么以技术咨询、设计评审的形式推进会比较顺畅。

常见问题

汇总了咨询这一主题时常见的问题。

什么是崩溃转储?能从中看到哪些信息?
崩溃转储是把崩溃那一刻的进程状态保存成文件,是一张类似事故现场静止画面的快照。事后可以确认异常代码、崩溃的线程及其调用堆栈、当时加载的模块,并且随着包含的内存量增加,还能看到堆上对象的内容。另一方面,走到崩溃之前的时间线,以及与通信、设备之间的外部状态往往会不足,所以实际工作中基本上要与日志和 heartbeat 组合使用。
WER 的 LocalDumps 在哪里配置?
在注册表的 HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps 下配置。实际工作中,与其使用全局配置,不如集中到 MyApp.exe 这样按应用划分的子键上更好管理。最先要看的值有三个:输出位置 DumpFolder、保留份数 DumpCount、种类 DumpType;不用分发额外工具,就能把崩溃后的转储留在本地。
小型转储和完整转储该选哪一个?
大致标准是:开发机、验证机用完整转储(DumpType=2);客户环境则看容量与机密要求,在小型转储(DumpType=1)和完整转储之间选。怀疑内存损坏、原生 DLL、COM、P/Invoke、长时间运行后的状态异常时,偏向完整转储更有利。不过完整转储体积大,也存在混入连接字符串、令牌等机密信息的风险,因此必须先定好保存位置、保留份数和访问权限。
ProcDump 在什么时候用?
WER LocalDumps 基本上面向崩溃,所以当你想连 hang 或 first chance exception 一起看、不想在注册表里常设配置、或者只想监视已经在运行的进程时,ProcDump 更合适。有代表性的选项包括:抓完整转储的 -ma、在未处理异常时采集的 -e、检测挂起的 -h、等待启动的 -w 等。以 first chance exception 为对象的 -e 1 容易产生大量转储,所以用 -n 加上上限、只短时间开启这类限定用法才现实。

作者简介

本文作者的个人简介页面。

Go Komura

小村软件有限公司 代表

以 Windows 软件开发、技术咨询与故障排查为中心,擅长难以复现的故障调查,以及既有资产仍在运行的项目。

返回博客列表