Share via


啟用事後偵錯

使用者模式例外狀況處理

例外狀況和中斷點

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

例外狀況處理常式優先順序

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

  1. 如果使用者模式偵錯工具目前附加至錯誤進程,則所有錯誤都會造成目標中斷至此偵錯工具。

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

  2. 如果沒有附加使用者模式偵錯工具,而且執行中的程式碼有自己的例外狀況處理常式 (例如 try - 除了) 之外,這個例外狀況處理常式會嘗試處理錯誤。

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

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

    在核心偵錯工具中,您可以使用 gh (Go With Exception Handled) 忽略錯誤並繼續執行目標。 您可以使用 gn (Go With Exception Not Handled) 略過核心偵錯工具並移至步驟 4。

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

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

DebugBreak 函式

如果已安裝事後偵錯工具,您可以藉由呼叫 DebugBreak 函式,刻意中斷使用者模式應用程式的偵錯工具。

指定事後偵錯工具

本節說明如何設定工具,例如 WinDbg 做為事後偵錯工具。 設定之後,每當應用程式當機時,就會自動啟動事後偵錯工具。

事後偵錯工具登錄機碼

Windows 錯誤報告 (WER) 會使用 AeDebug 登錄機碼中設定的值來建立事後偵錯工具程式。

HKLM\軟體\微軟\\ Windows NT CurrentVersion\AeDebug

感興趣的主要登錄值有兩個: 偵錯工具和Auto偵錯工具 登錄值會指定事後偵錯工具的命令列。 [自動登錄] 值會指定是否自動啟動事後偵錯工具,或是否先顯示確認訊息框。

偵錯工具 (REG_SZ)

這個REG_SZ值會指定將處理事後偵錯的偵錯工具。

除非偵錯工具位於預設路徑的目錄中,否則必須列出偵錯工具的完整路徑。

命令列是透過包含 3 個參數的 printf 樣式呼叫,從偵錯工具字串產生。 雖然順序是固定的,但不需要使用任何或所有可用的參數。

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

DWORD (%ld) - 事件控制碼重複到事後偵錯工具進程。 如果事後偵錯工具發出事件訊號,WER 會繼續目標進程,而不需要等待事後偵錯工具終止。 只有在問題已解決時,才會發出事件訊號。 如果事後偵錯工具終止而不發出事件訊號,WER 會繼續收集目標進程的相關資訊。

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

自動 (REG_SZ) 這個REG_SZ值一律為 01

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

如果 Auto 設定為 1,則會立即建立事後偵錯工具。

當您手動編輯登錄時,請非常小心,因為登錄的變更不正確可能不允許 Windows 開機。

範例命令列使用方式

許多事後偵錯工具都使用包含 -p 和 -e 參數的命令列,分別指出參數是 PID 和 Event () 。 例如,透過 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 %p 參數之間沒有參數:

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

32 和 64 位偵錯工具

在 64 位平臺上,偵錯工具 (REG_SZ) 和自動 (REG_SZ) 登錄值會針對 64 位和 32 位應用程式個別定義。 Windows (WOW) 金鑰上的額外 Windows 可用來儲存 32 位應用程式事後偵錯值。

HKLM\軟體\Wow6432Node\微軟\\ Windows NT CurrentVersion\AeDebug

在 64 位平臺上,針對 32 位進程使用 32 位事後偵錯工具,並針對 64 位進程使用 64 位偵錯工具。 這可避免在 32 位進程中將焦點放在 WOW64 執行緒而非 32 位執行緒上的 64 位偵錯工具。

對於許多事後偵錯工具,包括適用于 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 -I 。 (I 必須為大寫。) 此命令在使用後會顯示成功或失敗訊息。 若要同時使用 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 -iaecKeyString (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 -iaecKeyString (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 加上具有 -mp set MEM_PRI加值稅E 分頁) ,或 [完整 (所有記憶體- 相當於 「.dump /mA」) with -ma set。

對於有足夠的磁片磁碟機空間的系統,建議使用完整 ( ma) 擷取。

使用 -ma 搭配 -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 的其他資訊,請參閱 Microsoft Press 所發佈的 ProcDumpWindows SysInternals 系統管理員參考 Mark Russinovich 和 Aaron Margrestricted。

Just In Time (JIT) 偵錯

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

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

Windows 的偵錯工具

此範例示範如何編輯登錄,以執行使用 .jdinfo < address > 命令來顯示其他例外狀況資訊的初始命令 (-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""

安全性弱點

如果您考慮在與其他人共用的電腦上啟用事後偵錯,請參閱 事後偵錯期間的安全性