共用方式為


啟用事後偵錯

使用者模式例外狀況處理

例外狀況和斷點

最常見的應用程式錯誤稱為例外狀況。 這些包括存取違規、除以零錯誤、數值溢位、CLR 例外狀況,以及許多其他類型的錯誤。 應用程式也可能造成斷點中斷。 當 Windows 無法執行應用程式(例如,無法載入必要的模組時)或遇到斷點時,就會發生這些情況。 斷點可由調試程式插入程式代碼中,或透過DebugBreak函式叫用。

例外狀況處理程序優先順序

根據組態值和哪些調試程式為作用中,Windows 會以各種方式處理使用者模式錯誤。 下列順序顯示用於使用者模式錯誤處理的優先順序:

  1. 如果使用者模式調試程式目前附加至錯誤進程,所有錯誤都會造成目標進入這個調試程式。

    只要附加使用者模式調試程式,就不會使用其他錯誤處理方法,即使使用 gn (Go With Exception Not Handled) 命令也一樣

  2. 如果沒有附加使用者模式調試程式,且執行程式代碼有自己的例外狀況處理例程(例如 ,try - except),此例外狀況處理例程會嘗試處理錯誤。

  3. 如果沒有連結使用者模式調試程式,且 Windows 具有開啟的核心偵錯連線,而且錯誤是斷點中斷,Windows 會嘗試連絡核心調試程式。

    必須在 Windows 開機過程中開啟核心偵錯連線。 如果您想要防止使用者模式中斷中斷進入核心調試程式,您可以使用 KDbgCtrl 公用程式搭配 -du 參數。 如需如何設定內核偵錯連線及如何使用 KDbgCtrl 的詳細資訊,請參閱 設定偵錯

    在核心調試程式中,您可以使用 gh (Go With Exception Handled) 來忽略錯誤並繼續執行目標。 您可以使用 gn (使用例外狀況未處理) 略過核心調試程式,然後繼續進行步驟 4。

  4. 如果步驟 1、2 和 3 中的條件不適用,Windows 將會啟動 AeDebug 登錄值中設定的偵錯工具。 任何程式都可以事先選取為在此情況下使用的工具。 所選的程式稱為 驗屍調試程式

  5. 如果步驟 1、2 和 3 中的條件不適用,而且沒有註冊事後調試程式,Windows 錯誤報告 (WER) 會顯示訊息,並在任何可用時提供解決方案。 如果登錄中設定適當的值,WER 也會寫入記憶體轉儲檔案。 如需詳細資訊,請參閱 使用WER收集使用者模式傾印

DebugBreak 函式

如果已安裝事後調試程式,您可以藉由呼叫 DebugBreak 函式,刻意從使用者模式應用程式中斷調試程式。

指定事後調試程式

本節描述如何設定工具,例如 WinDbg 做為驗屍調試程式。 設定之後,每當應用程式當機時,就會自動啟動驗屍調試程式。

驗屍調試程式登錄機碼

Windows 錯誤報告 (WER) 會使用 AeDebug 登錄機碼中設定的值來建立驗屍調試程式程式。

HKLM\Software\Microsoft\Windows NT\CurrentVersion\AeDebug

感興趣的主要登錄值 有兩個:調試程式和 Auto調試程式登錄值會指定事後調試程式的 命令行。 [ 自動 登錄] 值會指定是否自動啟動驗屍調試程式,或先顯示確認消息框。

除錯程式 (REG_SZ)

這個REG_SZ值會指定將處理事後偵錯的調試程式。

除非調試程式位於預設路徑的目錄中,否則必須列出調試程式的完整路徑。

命令行是透過包含 3 個參數的 printf 樣式呼叫,從調試程式字串產生。 雖然訂單是固定的,但不需要使用任何或所有可用的參數。

DWORD (%ld) - 目標進程的進程識別碼。

DWORD (%ld) - 事件句柄重複到事後調試程序進程。 如果驗屍調試程序發出事件訊號,WER 會繼續目標進程,而不需要等待驗屍調試程序終止。 只有在問題已解決時,才會發出事件訊號。 如果事後調試程式在未發出事件訊號的情況下終止,WER 會繼續收集目標進程的相關信息。

void* (%p) - 目標行程位址空間中配置的JIT_DEBUG_INFO結構位址。 結構包含其他例外狀況信息和內容。

Auto (REG_SZ) 這個REG_SZ值一律 為 01

如果 Auto 設定為 0,則會在啟動事後偵錯程式之前顯示確認消息框。

如果 Auto 設定為 1,就會立即建立驗屍調試程式。

當您手動編輯登錄時,請非常小心,因為登錄的不當變更可能無法讓 Windows 開機。

範例命令行使用方式

許多驗屍調試程式會使用包含 -p 和 -e 參數的命令行來指出參數分別是 PID 和事件(分別)。 例如,透過 windbg.exe -I 安裝 WinDbg 會建立下列值:

Debugger = "<Path>\WinDbg -p %ld -e %ld -g"
Auto = 1

WER %ld %ld %ld %p 參數的使用方式有彈性。 例如, 不需要指定 WER 參數前後的任何參數。 例如,使用 procdump.exe -i 安裝 Windows Sysinternals ProcDump 會建立下列值,且 WER %ld %ld %ld %p 參數之間沒有參數:

Debugger = "<Path>\procdump.exe" -accepteula -j "c:\Dumps" %ld %ld %p
Auto = 1

32 和 64 位調試程式

在 64 位平臺上,調試程式 (REG_SZ) 和 Auto (REG_SZ) 登錄值會針對 64 位和 32 位應用程式個別定義。 Windows 上的其他 Windows(WOW) 機碼可用來儲存 32 位應用程式驗屍後偵錯值。

HKLM\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug

在 64 位平臺上,針對 32 位進程使用 32 位事後調試程式,針對 64 位進程使用 64 位調試程式。 這可避免 64 位調試程式將焦點放在 WOW64 線程,而不是 32 位線程的 32 位進程中。

對於許多事後調試程式,包括適用於 Windows 驗屍調試程式的偵錯工具,這牽涉到執行安裝命令兩次:一次使用 x86 版本,一次使用 x64 版本。 例如,若要使用 WinDbg 作為互動式驗屍調試程式, windbg.exe -I 命令會針對每個版本執行兩次。

64 位安裝:

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe –I

這會使用這些值來更新登錄機碼。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
Debugger = "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe" -p %ld -e %ld –g

32 位安裝:

C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe –I

這會使用這些值來更新登錄機碼。

HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug
Debugger = "C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe" -p %ld -e %ld –g

設定驗屍調試程式

適用於 Windows 的偵錯工具

適用於 Windows 調試程式的偵錯工具會設定為事後調試程式的所有支援。 install 命令想要讓進程以互動方式進行偵錯。

WinDbg

若要將驗屍除錯程式設定為 WinDbg,請執行 windbg -II(必須大寫。此命令會在使用成功或失敗訊息之後顯示。 若要同時使用 32 和 64 位應用程式,請針對 64 和 32 個調試程式執行 命令。

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe –I
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe –I

這是執行時 windbg -I ,AeDebug 登錄項目設定的方式。

Debugger = "<Path>\WinDbg -p %ld -e %ld -g"
Auto = 1

在範例中, <Path> 是調試程式所在的目錄。

如先前所述,-p 和 -e 參數會傳遞進程標識符和事件。

-g 會將 g (Go) 命令傳遞至 WinDbg,並繼續從目前的指令執行。

注意 傳遞 g (Go) 命令時發生重大問題。 此方法的問題在於例外狀況通常不一定會重複,因為程式代碼重新啟動時已不存在的暫時性狀況。 如需此問題的詳細資訊,請參閱 .jdinfo (使用 JIT_DEBUG_INFO)。

若要避免此問題,請使用 .jdinfo 或 .dump /j。 此方法可讓調試程式位於感興趣的程式代碼失敗內容中。 如需詳細資訊,請參閱 本主題稍後的 Just In Time (JIT) 偵 錯。

CDB

若要將驗屍調試程式設定為CDB,請執行 cdb -iae (Install AeDebug ) 或 cdb -iaec KeyString (Install AeDebug with Command)。

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe -iae
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe -iae

使用 -iaec 參數時,KeyString 會指定要附加至用來啟動事後調試程式的命令行結尾的字串。 如果 KeyString 包含空格,則必須以引弧括住。

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe -iaec [KeyString]
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe -iaec [KeyString]

此命令會在成功時顯示任何內容,如果失敗,則會顯示錯誤訊息。

NTSD

若要將驗屍調試程式設定為 NTSD,請執行 ntsd -iae (Install AeDebug) 或 ntsd -iaec KeyString (Install AeDebug with Command)。

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe -iae
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\ntsd.exe -iae

使用 -iaec 參數時,KeyString 會指定要附加至用來啟動事後調試程式的命令行結尾的字串。 如果 KeyString 包含空格,則必須以引弧括住。

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe -iaec [KeyString]
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\ntsd.exe -iaec [KeyString]

如果成功,此命令不會顯示任何內容,而且失敗時新控制台窗口發生錯誤。

注意 因為 -p %ld -e %ld -g 參數一律會先出現在事後調試程式的命令行上,所以您不應該使用 -iaec 參數來指定 -server 參數,因為除非 -server 出現在命令行上第一個,否則它將無法運作。 若要安裝包含此參數的驗屍調試程式,您必須手動編輯登錄。

Visual Studio JIT 調試程式

如果已安裝 Visual Studio,vsjitdebugger.exe將會註冊為驗屍調試程式。 Visual Studio JIT 調試程式打算讓進程以互動方式進行偵錯。

Debugger = "C:\WINDOWS\system32\vsjitdebugger.exe" -p %ld -e %ld

如果 Visual Studio 已更新或重新安裝,則會重新撰寫這個專案,並覆寫任何已設定的替代值。

Window Sysinternals ProcDump

Windows Sysinternals ProcDump 公用程式也可用於事後傾印擷取。 如需使用和下載 ProcDump 的詳細資訊,請參閱 ProcDump

如同 .dump WinDbg 命令,ProcDump 能夠以非互動方式擷取損毀的傾印。 擷取可能發生在任何 Windows 系統會話中。

ProcDump 會在傾印檔案擷取完成時結束,然後 WER 會報告失敗並終止錯誤進程。

使用 procdump -i 來安裝 procdump 和 -you 來卸載 32 位和 64 位驗屍偵錯的 ProcDump。

<Path>\procdump.exe -i

安裝和卸載命令會輸出在成功時修改的登錄值,以及失敗時的錯誤。

登錄中的 ProcDump 命令列選項會設定為:

Debugger = <Path>\ProcDump.exe -accepteula -j "<DumpFolder>" %ld %ld %p

ProcDump 會使用所有 3 個參數 - PID、事件和JIT_DEBUG_INFO。 如需JIT_DEBUG_INFO參數的詳細資訊,請參閱 下方的 Just In Time (JIT) 偵 錯。

擷取的傾印大小預設為 Mini (process/threads/handles/modules/address space),沒有大小選項集、MiniPlus (Mini plus MEM_PRIVATE pages) 和 -mp set 或 Full (所有記憶體 - 相當於 “.dump /mA”) 與 -馬 set。

對於有足夠的磁碟驅動器空間的系統,建議使用完整 (-馬) 擷取。

使用 -馬 搭配 -i 選項來指定所有記憶體擷取。 選擇性地提供傾印檔案的路徑。

<Path>\procdump.exe -ma -i c:\Dumps

對於磁碟驅動器空間有限的系統,建議使用 MiniPlus (-mp) 擷取。

<Path>\procdump.exe -mp -i c:\Dumps

要儲存傾印檔案的資料夾是選擇性的。 預設值為目前的資料夾。 資料夾應使用等於或優於 C:\Windows\Temp 所使用的 ACL 來保護資料夾。如需管理與資料夾相關安全性的詳細資訊,請參閱 事後偵錯期間的安全性。

若要將 ProcDump 卸載為事後調試程式,並還原先前的設定,請使用 -u (Uninstall) 選項。

<Path>\procdump.exe -u

如需 ProcDump 的其他資訊,請參閱 ProcDumpWindows SysInternals 系統管理員的參考 Mark Russinovich 和 Aaron Margosis Microsoft Press 所發行。

Just In Time (JIT) 偵錯

將內容設定為錯誤應用程式

如先前所述,使用 JIT_DEBUG_INFO 參數將內容設定為造成當機的例外狀況非常理想。 如需詳細資訊,請參閱 .jdinfo (使用 JIT_DEBUG_INFO)。

Windows 的偵錯工具

這個範例示範如何編輯登錄以執行使用 .jdinfo <位址> 命令來顯示其他例外狀況資訊的初始命令 (-c),並將內容變更為例外狀況的位置(類似於使用 .ecxr 將內容設定為例外狀況記錄的方式)。

Debugger = "<Path>\windbg.exe -p %ld -e %ld -c ".jdinfo 0x%p"
Auto = 1

%p 參數是目標進程位址空間中JIT_DEBUG_INFO結構的位址。 %p 參數會預先附加 0x,使其解譯為十六進位值。 如需詳細資訊,請參閱 .jdinfo (使用 JIT_DEBUG_INFO)。

若要偵錯混合 32 和 64 位應用程式,請設定 32 和 64 位登錄機碼(如上所述),將適當的路徑設定為 64 位和 32 位WinDbg.exe的位置。

使用 .dump 建立傾印檔案

若要在發生包含JIT_DEBUG_INFO數據失敗時擷取傾印檔案,請使用 .dump /j <位址>。

<Path>\windbg.exe -p %ld -e %ld -c ".dump /j %p /u <DumpPath>\AeDebug.dmp; qd"

使用 /u 選項來產生唯一的檔名,以允許自動建立多個傾印檔案。 如需選項的詳細資訊,請參閱 .dump (建立傾印檔案)。

建立的傾印會將JITDEBUG_INFO數據儲存為預設例外狀況內容。 不使用 .jdinfo 來檢視例外狀況資訊並設定內容,請使用 .exr -1 來顯示例外狀況記錄和 .ecxr 來設定內容。 如需詳細資訊,請參閱 .exr (顯示例外狀況記錄).ecxr (顯示例外狀況內容記錄)。

Windows 錯誤報告 - q / qd

偵錯會話結束的方式會判斷 Windows 錯誤報告 是否報告失敗。

如果在調試程式關閉之前使用 qd 中斷偵錯工作階段,WER 會報告失敗。

如果使用 q 結束偵錯會話(或調試程式關閉而不中斷連結),WER 將不會回報失敗。

附加 ;q;qd 到命令字串的結尾,以叫用所需的行為。

例如,若要允許 WER 在 CDB 擷取傾印之後回報失敗,請設定此命令字串。

<Path>\cdb.exe -p %ld -e %ld -c ".dump /j 0x%p /u c:\Dumps\AeDebug.dmp; qd"

此範例可讓 WER 在 WinDbg 擷取傾印之後回報失敗。

<Path>\windbg.exe -p %ld -e %ld -c ".dump /j %p /u <DumpPath>\AeDebug.dmp; qd""

安全性弱點

如果您考慮在與其他人共用的計算機上啟用驗屍偵錯,請參閱 事後偵錯期間的安全性。