Windows 應用的 crash dump 收集入門 - 先搞清楚 WER / ProcDump / WinDbg 怎麼分工

· · Windows 開發, 故障調查, crash dump, WER, ProcDump, WinDbg

在 Windows 應用上,只要「偶爾才會掛」這種症狀出現,光靠日誌往往追不下去。

特別是下列情境:

  • 只在客戶環境會發生
  • 有抓到例外訊息,但呼叫端的上下文不夠
  • 不只是 C# / .NET 的 managed 層,還牽涉 COM、P/Invoke、原生 DLL、廠商 SDK
  • 只有在長時間運轉後才掛

這時候 crash dump 就派得上用場。只要在 crash 當下把行程狀態存成檔案,之後就能讀到例外代碼、掛掉那條 thread 的堆疊、當時載入的模組、以及部分或整塊的記憶體。

在 Windows 上,思路順序是:先用 WER 的 LocalDumps,有需要再搭 Sysinternals 的 ProcDump;真的想自己控制了,再用 MiniDumpWriteDump。本文就以 Windows 桌面應用、常駐應用、Windows 服務、設備整合工具等為前提,整理 crash dump 收集的第一步。

1. 先下結論

先把最要掌握的重點列出來:

  • 以應用為單位設定 WER LocalDumps 是最穩當的做法,不用額外部署工具,也能在 crash 後把 dump 留在本地。
  • 重現率低的現場調查、或要看 first chance exception / hang,就用 ProcDump
  • 自製收集擺到最後再想 大概剛好。真的需要再評估 MiniDumpWriteDump 就行。
  • 和 dump 同等重要的是 PDB 與發布 binary 的保存。只有 dump 沒有符號,能讀到的資訊會大幅減少。
  • full dump 威力大,但檔案大小與機敏資訊外洩風險也大。保存位置、保存份數、存取權限、分享流程要先定好。

入門階段建議的配置大概是這樣:

環境 起手式
開發機/驗證機 以應用為單位設定 WER LocalDumps,先用 DumpType=2 取 full dump
客戶環境/現場機 依容量與機敏要求選 DumpType=12;只在必要時補上 ProcDump
長時間運轉或 hang 調查 WER 之外再評估 ProcDump 的 -h-e 1
想自帶 UI、附帶日誌 以獨立行程為前提,用 MiniDumpWriteDump 做自家收集

簡單說就是:先 WER,再 ProcDump,最後自製。反過來的順序做,設計通常會變重。

2. crash dump 能告訴我們什麼

crash dump 是「那一刻的快照」,比起監視錄影,它更像事故現場的靜止畫。

所以下列資訊通常很容易拿到:

  • 是哪個例外代碼
  • 是哪條 thread 掛掉
  • 當下的呼叫堆疊
  • 當時載入的模組
  • 依你包進多少記憶體,還能看到 heap 的狀態、物件內容

但下列資訊光靠 dump 就比較不夠:

  • 走到這一步的時序
  • 幾小時前就在上升的趨勢
  • 和通訊或設備之間的外部狀態
  • 崩潰前的輸入或業務情境

所以實務上 不要只靠 dump 打單挑,要搭配日誌與 heartbeat

3. 收集方法全貌

入門階段要掌握的 Windows 應用 dump 收集方式,有下列 4 種:

方法 適合情境 優勢 注意事項
WER LocalDumps 想先常態化的 crash 收集 Windows 內建,易以應用為單位設定 主要針對 crash;hang 與細部條件分流較弱
ProcDump 重現率低的調查、hang、first chance exception 觸發條件多,容易在現場部署 變成外部工具的運維
工作管理員的建立 dump 手動抓當下狀態 GUI 現場抓 不是自動收集
MiniDumpWriteDump 想做自家診斷功能 容易把附帶日誌或自訂 metadata 綁一起 寫不好反而會把自己搞壞

對入門者來說,比起「用什麼抓」,更要先決定「在什麼條件」「抓到哪」「抓多大」

4. 起手式推薦 WER LocalDumps

4.1 先看的登錄檔值

Windows Error Reporting (WER) 內建了 LocalDumps,可以在 crash 後把 user-mode dump 存到本地。不用額外派發工具,起手式相當好用。

基本 key 是:

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

你可以在這裡放全域設定,但實務上更建議把設定放在 以應用為單位的子 key 下。

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

最先看的值有 3 個:

意義 起手式建議
DumpFolder dump 的輸出位置 切一個專用資料夾
DumpCount 保留份數 從 5〜10 起
DumpType 0=自訂、1=mini、2=full 先用 2;容量吃緊再改 1

4.2 以應用為單位的設定範例

舉例來說,想把 MyApp.exe 的 full dump 存到 C:\CrashDumps\MyApp,最多保留 10 份,可以這樣設:

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

這段的重點:

  • 範圍限定到 MyApp.exe,不是全域
  • 輸出位置切到專用資料夾
  • 起手式先用 full dump
  • 保留份數限制為 10

4.3 確認真的有抓到

設好之後,不要直接等正式環境自然發生,一定要先在驗證環境親自抓一次 比較安全。

確認重點:

  1. .dmp 會不會出現在預期資料夾
  2. 檔案大小是否符合運維設想
  3. 用 WinDbg 能不能打開
  4. 事件檢視器的 Application 日誌有沒有對應 crash 事件

5. 何時用 ProcDump

WER 就夠用的情境不少,但下列情境 ProcDump 更方便:

  • 不想常設登錄檔
  • 只想監看某個已在跑的行程
  • 只想監看下一次啟動的行程
  • 要看 first chance exception
  • 要抓 hang
  • 想用效能計數器或其他條件觸發

5.1 常用選項

入門階段只要記下列這些,就能打相當多仗:

選項 意義
-ma full dump
-mp MiniPlus dump
-e 未處理例外時抓 dump
-e 1 first chance / second chance 例外都抓
-h 視窗 hang 時抓
-w 等目標行程啟動
-x 由 ProcDump 啟動並監看目標
-n 最多抓幾份 dump
-accepteula 首次 EULA 自動同意

5.2 代表性指令

對已啟動的行程,未處理例外時抓 full dump

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

等下次啟動,未處理例外時抓 full dump

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

由 ProcDump 啟動並繼續監看

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

要抓 hang

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

5.3 為什麼不要把 -i 當起手式

ProcDump 有 -i 可以註冊成 postmortem debugger,功能很強,但 會動到整台機器的 crash 時行為,入門階段拿它來起手式太重。

起手式建議從 WER 的應用單位設定ProcDump 的 -w / -x / 指定 PID 開始,比較好掌握。

6. 自製收集用 MiniDumpWriteDump 的思路

自製收集適合下列情境:

  • 想在 UI 放一顆「儲存診斷資訊」按鈕
  • 想把 dump、日誌、設定、trace ID 綁在一起
  • 想連同關聯的子行程或輔助行程一起打包
  • 上傳前想做自家的資料遮罩或壓縮

這邊主角 API 是 MiniDumpWriteDump

不過它有一些癖好,入門階段最不要偏掉的有 2 點:

  1. 如果可以,從另一個行程去 dump 對象行程
  2. DbgHelp 系列以 single-threaded 的前提使用

7. mini / full / 中型 dump 怎麼選

這裡相當多人猶豫。實務上照下表思考會比較順:

種類 適合情境 優勢 注意事項
mini dump 想先廣佈、方便分享 小、好傳 能還原的狀態深度有限
full dump 以查原因為優先,牽涉原生邊界或 heap 資訊最多 檔案大、機敏資訊外洩風險高
MiniPlus / Custom mini 不夠、full 又太重 取平衡 需要調參的知識

給入門者的建議其實很單純:

  • 開發機/驗證機直接 full dump
  • 客戶環境依運維條件選 mini 或 full
  • 懷疑是記憶體破壞、原生 DLL、COM、P/Invoke、或長時間運轉後的狀態異常,偏 full

8. 運維上要先決定的事

dump 收集常常是運維面先出事,而不是實作面。請先把下列事項釐清。

8.1 PDB 與 binary 要怎麼保存

這件事最重要。

  • 實際發布的 EXE / DLL 版本
  • 該版本對應的 PDB
  • 是從哪個 commit / 哪條 build pipeline 產的
  • 安裝檔與發布物的版本資訊

8.2 要輸出到哪裡、保留幾份

full dump 會相當大,一開始就先定:

  • 不要放在系統槽根目錄
  • 切到專用資料夾
  • DumpCount-n 設上限
  • 長期保存與一次保存分開

8.3 誰可以看這些 dump

full dump 有可能混入機敏或個人資訊:

  • 明文設定
  • 連線字串
  • token 或憑證
  • 崩潰前正在處理的業務資料
  • 檔案路徑或使用者名稱

所以 「抓什麼」的設計,要與「誰可以接觸」一起定

9. 拿到 dump 後的最短分析路線

拿到 dump 之後要做的事其實很樸實:

9.1 安裝 WinDbg

現在可從 Microsoft Store 或 winget 安裝。

winget install Microsoft.WinDbg

9.2 開啟 dump

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

9.3 設定符號

先接通 Microsoft 公開符號,再把自家 PDB 的路徑加進去。

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

9.4 先看自動分析

!analyze -v

之後依序看:

  • 是哪個例外代碼
  • faulting module 是什麼
  • 自家程式碼在堆疊上露到哪
  • 除了例外 thread,其他 thread 有沒有奇怪的等待或卡住

10. 常見踩坑

10.1 dump 有了,但 PDB 沒了

這種情況不少。dump 有抓到,但沒有符號就讀得很片段。
設定 dump 的同一時間,就把 PDB 的保存設計一起做

10.2 沒檢查 DumpFolder 的 ACL

在服務或已做權限隔離的行程上,這裡很容易空轉。
先確認「那個行程真的能寫進去嗎」

10.3 持續把 full dump 往正式環境的系統槽寫

這是容量事故的常客。
保留份數限制與輸出位置分離,一開始就要配。

10.4 想用 WER 一手包 hang 的情境

WER LocalDumps 主要對 crash 有效。
hang 或 first chance exception,ProcDump 有些情境更合

10.5 永遠開著 -e 1,被例外洪流淹沒

first chance exception 很好用,但數量就是多。
設份數上限、短時間才開、限縮目標 才實務。

11. 總結

在重現率低的故障場景裡,crash dump 是相當有力的觀測點。特別是 Windows 應用牽涉 COM、P/Invoke、原生 DLL、或長時間運轉時,一開始就先把「掛掉後要留下什麼」定清楚,非常值得。

推薦的順序很單純:

  1. 先把 WER LocalDumps 以應用為單位設定好
  2. 必要時再加 ProcDump
  3. 想進一步控制,再以獨立行程為前提使用 MiniDumpWriteDump

按這個順序走,比較不會走偏。

12. 參考資料

共用相同標籤的最新文章。能以相近的主題延伸理解。

與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。

本文連結到以下服務頁面,歡迎從最接近的入口查看。

作者檔案

本文作者的個人檔案頁面。

Go Komura

小村軟體有限公司 代表

以 Windows 軟體開發、技術諮詢與故障調查為中心,在難以重現的故障調查與既有資產仍在運作的專案上具有優勢。

回到部落格一覽