Windows 當機傾印收集入門 - WER/ProcDump/WinDbg
· 更新日期: · Go Komura · Windows 開發, 缺陷調查, 當機傾印, WER, ProcDump, WinDbg
更新紀錄(2 筆,最後更新 2026年09月04日)
本文的修改紀錄。已保存的更新前版本,可透過附有 DOI 的永久連結閱讀。
引用本文(DOI: 10.5281/zenodo.21616306)
本文保存於 Zenodo。以下同時提供一律指向最新版本的 DOI,以及固定於您正在閱讀版本的 DOI。
Go Komura(2026)。〈Windows 當機傾印收集入門 - WER/ProcDump/WinDbg〉。小村軟體有限公司。https://doi.org/10.5281/zenodo.21616306 https://comcomponent.com/zh-TW/blog/2026/03/16/008-windows-app-crash-dump-collection-introduction/
- DOI(最新版本)
- 10.5281/zenodo.21616306
- DOI(此版本)
- 10.5281/zenodo.22297145
Windows 應用程式一旦開始出現「偶爾才會當掉」的狀況,光靠日誌追不下去的場面相當多。
特別難處理的是這幾種狀況。
- 只在客戶環境發生
- 例外訊息有拿到,但呼叫端的來龍去脈不夠
- 不只是 C# / .NET 的 managed 側,還牽涉 COM、P/Invoke、native DLL、廠商 SDK
- 只有在長時間運轉後才當掉
這種時候派得上用場的就是當機傾印。只要把當機時點的處理程序狀態寫成檔案,事後就能讀到例外代碼、當掉的執行緒的堆疊、當時載入的模組,以及部分或全部的記憶體。
在 Windows 上,先用 WER 的 LocalDumps,必要時再加上 Sysinternals ProcDump,還想進一步控制才用 MiniDumpWriteDump,照這個順序思考最容易理解。本文以 Windows 桌面應用程式、常駐應用程式、Windows 服務、設備介接工具等為前提,梳理當機傾印收集的第一步。
flowchart TB
accTitle: 思考收集手段的順序
accDescr: 說明 Windows 的當機傾印收集,先用 WER 的 LocalDumps,必要時再用 Sysinternals 的 ProcDump,還想進一步控制才用 MiniDumpWriteDump,照這個順序思考最容易理解的圖。
w1["先用 WER LocalDumps"] --> w2["必要時再加 ProcDump"]
w2 --> w3["還想進一步控制就用 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 才是基本。
flowchart TB
accTitle: 傾印與日誌的組合
accDescr: 說明當機傾印像事故現場的靜止影像,對那一瞬間的狀態很強,而走到那一步為止的時序與外部狀態則由日誌與 heartbeat 補足,因此基本上要兩者搭配使用的圖。
d1["當機傾印〔瞬間的靜止影像〕"] --> mix["組合起來調查"]
d2["日誌與 heartbeat〔時序〕"] --> mix
d1 -.-> s1["對例外代碼與堆疊很強"]
d2 -.-> s2["對走到那一步的經過很強"]
圖 2: 靜止影像的傾印與時序的日誌,擅長的領域切得很乾淨。
3. 收集方法的全貌
Windows 應用程式的傾印收集中,入門階段要掌握的方法有下列 4 種。
| 方法 | 適合的場面 | 強項 | 注意事項 |
|---|---|---|---|
| WER LocalDumps | 想先常設下來的當機收集 | Windows 標準功能。容易以應用程式為單位設定 | 基本上針對當機。hang 與細部的條件分支較弱 |
| ProcDump | 重現率低的調查、hang、first chance exception | 觸發條件多。容易投入實務現場 | 會變成外部工具的維運 |
| 工作管理員的建立傾印 | 想手動取得現在的狀態 | 用 GUI 當場就能取得 | 不是自動收集 |
MiniDumpWriteDump |
想做自己的診斷功能 | 容易把附帶日誌或自訂中繼資料合在一起 | 實作草率反而會把東西弄壞 |
對新手來說最重要的是,比起「用什麼取」,更要先決定「在什麼條件下」「取到哪裡」「取多大」。
flowchart TB
accTitle: 比道具更早要決定的事
accDescr: 說明當機傾印收集要先決定在什麼條件下、取到哪裡、取多大這三件事,之後才進到用什麼取這個道具選擇的圖。
c1["在什麼條件下取"] --> firstq["先決定的 3 點"]
c2["輸出到哪裡"] --> firstq
c3["取多大"] --> firstq
firstq --> tool["然後才選道具"]
圖 3: 條件、輸出位置與大小決定好之後,選道具就不會猶豫。
4. 起手最推薦 WER LocalDumps
4.1 最先要看的登錄檔值
Windows Error Reporting (WER) 有 LocalDumps,可以在當機後把使用者模式傾印存到本機。不必散發額外工具,作為第一步相當好處理。
基本的機碼在這裡。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps
你也可以在這裡放全域設定,但實務上收攏到 以應用程式為單位的子機碼 更好處理。
flowchart TB
accTitle: LocalDumps 設定的放置位置
accDescr: 說明雖然可以把全域設定放在 LocalDumps 機碼正下方,但實務上收攏到像 MyApp.exe 這種以應用程式為單位的子機碼更好處理的圖。
key1["LocalDumps 機碼"] --> g1["正下方的全域設定"]
key1 --> a1["以應用程式為單位的子機碼"]
a1 -.-> a2["實務上這一邊比較好處理"]
圖 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,想在 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
這個範例的重點有 4 個。
- 限定在
MyApp.exe,而不是全域 - 把輸出位置分離到專用資料夾
- 起手先用完整傾印
- 把保留份數限制在 10
4.3 確認有沒有真的取到
設定放進去之後,在正式環境等它自然發生之前,先在驗證環境確實取到 1 次 比較安全。
要確認的是這 4 點。
- 預期的資料夾裡會不會出現
.dmp - 檔案大小是否符合維運上的設想
- WinDbg 能不能打開
- 事件檢視器的「應用程式」記錄檔裡看不看得到 crash
flowchart TB
accTitle: 設定後的驗證流程
accDescr: 說明設定放進去後,在正式環境等它自然發生之前,先在驗證環境確實取到 1 次,並確認資料夾裡有沒有傾印、大小是否符合設想、WinDbg 能不能打開、事件檢視器裡看不看得到 crash 的流程圖。
v1["放入設定"] --> v2["在驗證環境刻意讓它當掉"]
v2 --> v3["確認傾印是否存在與大小"]
v3 --> v4["確認 WinDbg 能否打開"]
v4 --> v5["確認事件檢視器的記錄檔"]
圖 5: 在等正式環境自然發生之前,先在驗證環境確實取到 1 次。
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 的機碼,要嘛改用全域設定那邊來試,二選一。
flowchart TB
accTitle: 子機碼名稱必須一致的陷阱
accDescr: 說明 LocalDumps 的子機碼名稱必須和現在要弄當掉的 EXE 檔名一致,否則不會產出傾印,因此驗證時要暫時建立 CrashTest.exe 的機碼,或改用全域設定來試的圖。
t1["只建立 MyApp.exe 的機碼"] --> t2["讓 CrashTest.exe 當掉"]
t2 --> t3["不會產出傾印"]
t3 -.-> t4["機碼名稱要和當掉的 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> |
自訂傾印。以 16 進位指定 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 切入比較好處理。
flowchart TB
accTitle: 不把 -i 當成第一步的理由
accDescr: 說明 ProcDump 的 -i 是註冊成 postmortem debugger 的強大用法,但會動到整台機器當機時的行為,因此入門階段從 WER 的應用程式單位設定,或 ProcDump 的 -w、-x、指定 PID 切入比較好處理的圖。
i1["用 ProcDump 的 -i 註冊"] --> i2["動到整台機器的行為"]
i2 -.-> i3["對入門的第一步來說太重"]
i4["一開始用應用程式單位的設定"] --> i5["WER 的應用程式單位設定"]
i4 --> i6["ProcDump 的 -w、-x 或指定 PID"]
圖 7: 從影響範圍收在應用程式單位的入口開始。
6. 自製收集使用 MiniDumpWriteDump 時的思路
適合自製收集的,例如是這些場面。
- 想在 UI 上放一個「儲存診斷資訊」的按鈕
- 想把日誌、設定、追蹤 ID 和傾印綁在一起
- 想把相關的子處理程序或輔助處理程序也一起收進來
- 想在上傳前加入自訂的遮罩或壓縮
這裡的核心 API 是 MiniDumpWriteDump。
不過這裡有點脾氣。入門階段特別不想弄錯的是下面 2 點。
- 可以的話,從傾印對象以外的處理程序呼叫
- DbgHelp 系列以 single-threaded 為前提來使用
flowchart TB
accTitle: 自製收集不想弄錯的 2 點
accDescr: 說明用 MiniDumpWriteDump 自製收集時,要注意可以的話從傾印對象以外的處理程序呼叫,以及以 single-threaded 為前提使用 DbgHelp 系列這 2 點的圖。
md1["用 MiniDumpWriteDump 自製收集"] --> md2["從別的處理程序呼叫"]
md1 --> md3["DbgHelp 以 single-threaded 為前提"]
md2 -.-> md4["實作草率反而會把東西弄壞"]
md3 -.-> md4
圖 8: 自製收集的脾氣,集中在呼叫的位置與執行緒這 2 點。
7. 迷你傾印/完整傾印/中間大小怎麼選
在這裡猶豫的人相當多。把實務上的選法整理成一張表。
| 種類 | 適合的場面 | 好處 | 注意事項 |
|---|---|---|---|
| 迷你傾印 | 想先廣泛放進去、想讓分享輕一點 | 檔案小、容易傳送 | 還原狀態的深度較弱 |
| 完整傾印 | 想以原因調查為優先,懷疑 native 邊界或堆積 | 能取得的資訊多 | 檔案大、機密混入的風險高 |
| MiniPlus/Custom | 迷你不夠,完整又太重 | 能取得平衡 | 需要調整的知識 |
給新手的建議相當單純。
- 開發機/驗證機用完整傾印
- 客戶環境依維運條件在迷你與完整之間選
- 懷疑是記憶體毀損、原生 DLL、COM、P/Invoke,或長時間運轉後的狀態異常,就偏向完整
flowchart TB
accTitle: 傾印種類的起手選法
accDescr: 說明開發機或驗證機用完整傾印,客戶環境依維運條件選迷你或完整,懷疑記憶體毀損、原生邊界或長時間運轉後的狀態異常就偏向完整的選法圖。
e1{"要在哪種環境取得"}
e1 -->|"開發機/驗證機"| f1["完整傾印"]
e1 -->|"客戶環境"| f2["依維運條件選迷你或完整"]
f2 -.->|"有毀損味道或原生邊界"| f1
圖 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 的名字聽起來小,內容其實相當偏完整。根據文件,它包含 全部的 private 記憶體,以及全部可 read/write 的 image/mapped 記憶體,並在此之上 只排除超過 512MB 的最大 private 區域 來壓低大小。結果它的定位就是「詳細程度和完整傾印相當,但大小是完整的 10%〜75%」。
不過有 2 個注意事項。
- CLR 處理程序因為偵錯上的限制,即使指定
-mp也會以完整(-ma)的形式採集。 在 .NET 應用程式上指望 MiniPlus 縮小檔案,多半會落空 - 如果想壓低大小的動機是「想減少機密資訊混入」,那不要用 MiniPlus,從迷你傾印那一邊思考比較直接了當
flowchart TB
accTitle: MiniPlus 的定位與限制
accDescr: 說明 MiniPlus 包含全部的 private 記憶體與可 read/write 的 image 或 mapped 記憶體,只排除超過 512MB 的最大 private 區域,大小落在完整的一成到七成多,但 CLR 處理程序即使指定 -mp 也會以完整的形式採集的圖。
mp1["以 MiniPlus 採集"] --> mp2["private 記憶體幾乎全部包含"]
mp2 --> mp3["只排除巨大的 private 區域"]
mp3 --> mp4["比完整小又詳細"]
mp1 -.->|"CLR 處理程序的情況"| mp5["會以完整的形式採集"]
圖 10: MiniPlus 的內容偏向完整,在 .NET 應用程式上縮小檔案的效果不會出現。
8. 維運上要先決定的事
傾印收集比起實作,更常在維運上跌倒。以下列出想先決定好的事。
8.1 PDB 與二進位檔要怎麼留
這件事最重要。
- 散發出去的 EXE/DLL 的正確版本
- 對應那個版本的 PDB
- 是用哪個 commit/哪條建置管線做出來的
- 安裝程式與散發物的版本資訊
8.2 要輸出到哪裡、留幾份
完整傾印會變得相當大。輸出位置與保留方針從一開始就決定好比較安全。
- 不要就這樣丟在系統磁碟機的根目錄
- 分離到專用資料夾
- 用
DumpCount或-n設上限 - 把長期保存與一次保存分開
8.3 誰可以看
完整傾印裡可能混入機密資訊或個人資料。
- 明文設定
- 連線字串
- 權杖與認證資訊
- 當機前正在處理的業務資料
- 檔案路徑與使用者名稱
所以必須 在設計「怎麼取」的同時,也決定「誰可以碰」。
flowchart TB
accTitle: 維運上要先決定的 3 點
accDescr: 說明當機傾印收集比起實作更容易在維運上跌倒,因此要先決定 PDB 與二進位檔的保存、輸出位置與保留份數,以及誰可以看這個存取方針的圖。
op1["PDB 與二進位檔的保存"] --> op4["先決定好"]
op2["輸出位置與保留份數"] --> op4
op3["誰可以看"] --> op4
op4 -.-> op5["比起實作更容易在維運上跌倒"]
圖 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 底下。覺得「傾印沒有出來」時,先懷疑這裡。
flowchart TB
accTitle: 找不到傾印時該去哪裡找
accDescr: 說明沒有設定 DumpFolder 時的預設是 LOCALAPPDATA 底下的 CrashDumps,而服務的當機會輸出到各執行帳戶的設定檔資料夾,因此覺得沒有出來時要先懷疑那裡的圖。
fq1["找不到傾印"] --> fq2{"當時是以哪種形式在執行"}
fq2 -->|"一般應用程式"| fp1["LOCALAPPDATA 底下的 CrashDumps"]
fq2 -->|"服務"| fp2["執行帳戶的設定檔底下"]
fp2 -.-> fp3["SystemProfile 或 ServiceProfiles"]
圖 12: 預設的輸出位置會隨帳戶而不同,所以要從尋找的位置開始懷疑。
9.3 設定符號
先讓 Microsoft 公開符號處於可用的狀態,之後再加上自己 PDB 的位置。
.symfix C:\Symbols\Microsoft
.sympath+ C:\Symbols\MyApp
.reload
9.4 先看自動分析
!analyze -v
在此之上,
- 是哪個例外代碼
- faulting module 是什麼
- 自己的程式碼在堆疊上露出到哪裡
- 例外執行緒之外,有沒有可疑的等待或卡住
依序查看這幾點。
flowchart TB
accTitle: 取到之後最短的分析動線
accDescr: 說明安裝 WinDbg、打開傾印、設定 Microsoft 公開符號與自己的 PDB,先看 analyze -v 的自動分析,再依序確認例外代碼、faulting module、自己的程式碼露出到哪裡,以及其他執行緒有沒有卡住的流程圖。
an1["安裝 WinDbg"] --> an2["打開傾印"]
an2 --> an3["設定符號與 PDB"]
an3 --> an4["先看自動分析"]
an4 --> an5["依序讀例外代碼與堆疊"]
圖 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 決定的方針有出入。
flowchart TB
accTitle: DumpFolder 的 ACL 檢查流程
accDescr: 說明服務或做過權限分離的處理程序在寫入上容易落空,因此要用 icacls 檢查目前的 ACL,不足時給執行帳戶加上帶繼承的變更權,並把繼承範圍與閱覽方針對照的流程圖。
ac1["用 icacls 查看目前的 ACL"] --> ac2{"執行帳戶寫得進去嗎"}
ac2 -->|"寫不進去"| ac3["加上帶繼承的變更權"]
ac2 -->|"寫得進去"| ac4["就這樣維運"]
ac3 -.-> ac5["繼承範圍要與閱覽方針對照"]
圖 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、native DLL、長時間運轉時,一開始就先決定好「當掉之後會留下什麼」很有價值。
建議的順序很簡單。
- 先以應用程式為單位放入 WER LocalDumps
- 必要時再加上 ProcDump
- 還想進一步控制時,以獨立處理程序為前提使用
MiniDumpWriteDump
照這個順序推進,比較不容易大幅走偏。
12. 參考資料
- 收集使用者模式傾印 - Win32 apps | Microsoft Learn
- ProcDump v11.1 - Sysinternals | Microsoft Learn
- MiniDumpWriteDump function (minidumpapiset.h) - Win32 | Microsoft Learn
- User-mode dump files - Windows drivers | Microsoft Learn
- 分析使用者模式傾印檔案 - Windows drivers | Microsoft Learn
- 安裝 Windows 偵錯器 - Windows drivers | Microsoft Learn
- Symbol path for Windows debuggers - Windows drivers | Microsoft Learn
- !analyze (WinDbg) - Windows drivers | Microsoft Learn
- Troubleshoot processes by using Task Manager - Windows Server | Microsoft Learn
- Enabling Postmortem Debugging - Windows drivers | Microsoft Learn
- MINIDUMP_TYPE enumeration (minidumpapiset.h) - Win32 | Microsoft Learn
- icacls - Windows commands | Microsoft Learn
- NotMyFault - Sysinternals | Microsoft Learn
相關文章
共用相同標籤的最新文章。能以相近的主題延伸理解。
Windows 應用程式當機時留下日誌與傾印的設計
為了讓 Windows 應用程式因非預期的例外或程式錯誤而當掉之後,仍留下能追查原因的佐證資料,本文梳理一般日誌、最終當機標記、WER LocalDumps 與監控處理程序應該如何搭配。
用 WinDbg + SOS 解讀當機傾印檔 ── 收集之後的實務分析入門
本文說明如何用 WinDbg 與 SOS 擴充功能實際讀取已收集的 Windows 當機傾印檔。內容涵蓋符號路徑設定、以 !clrstack・!pe・!dumpheap -stat・!gcroot 追蹤例外與記憶體洩漏的方法、原生當機的 !analyze -v,以及與 do...
Time Travel Debugging ── 把長期運轉中無法重現的問題「錄下來」再倒回去
一個月才出現一次的問題,當機傾印只拍得到結果。本文說明如何用 WinDbg 的 Time Travel Debugging(TTD) 錄下執行並倒回,涵蓋 TTD.exe 的錄製設計、環形緩衝區、TTD.Calls 查詢,以及和傾印的分工。
睡眠・休眠・Modern Standby 與長時間執行的應用程式 ── 用設計預防「半夜停止運轉」
本文將從 S3 睡眠、休眠、Modern Standby 的差異出發,整理長時間執行的 Windows 應用程式「早上一看才發現已經停止」的原因,並解說睡眠期間計時器與 TCP 連線的行為,以及透過 SetThreadExecutionState 進行抑止的做法。
網路磁碟機與 UNC 路徑的陷阱 ── 業務應用程式處理檔案伺服器(共用資料夾)的實務
整理業務應用程式對共用資料夾進行輸出・監控時常見的麻煩。說明磁碟機代號(Z:)為何無法從服務中看到、各執行帳戶所需的權限、錯誤 1219,以及 FileSystemWatcher 的注意事項。
相關主題
與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。
Windows 技術主題
彙整 KomuraSoft LLC 關於 Windows 開發、故障調查與既有資產活用文章的主題中心。
與本主題相關的服務
本文連結到以下服務頁面,歡迎從最接近的入口查看。
故障調查 & 根本原因分析
把當機傾印、日誌與重現條件組合起來釐清原因的流程,與缺陷調查、原因分析這類主題相當契合。尤其是只在實務現場才發生的當機,或長時間運轉後才出現的故障,觀測設計本身就會變成關鍵。
技術諮詢 & 設計審查
如果想連同正式環境要採集什麼、傾印與日誌怎麼織進設計,以及權限與保存方針一起梳理清楚,以技術諮詢、設計審查的形式推進會比較順。
常見問題
整理諮詢這個主題時常見的問題。
- 什麼是當機傾印?能看出什麼?
- 它是把當機那一瞬間的處理程序狀態存成檔案,像事故現場靜止影像一樣的快照。事後可以查看例外代碼、當掉的執行緒與它的呼叫堆疊、當時載入的模組,並依照納入的記憶體多寡,連堆積上物件的內容都能看到。另一方面,走到當機為止的時序,以及與通訊或設備之間的外部狀態容易不足,所以實務上基本上要搭配日誌與 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 加上上限、短時間且限定範圍地使用比較實際。