共用方式為


使用管理式偵錯助手診斷錯誤

備註

本文專屬於 .NET Framework。 它不適用於較新的 .NET 實作,包括 .NET 6 和更新版本。

Managed 除錯助理 (MDA)是除錯輔助程式,可搭配 Common Language Runtime (CLR)提供執行階段狀態的相關資訊。 助理會生成有關運行時事件的資訊訊息,而這些事件無法以其他方式捕捉。 您可以使用 MDA 來隔離在 Managed 與 Unmanaged 程式代碼之間轉換時所發生的難以尋找的應用程式錯誤。

您可以將金鑰新增至 Windows 登錄或設定環境變數,來 啟用或停用 所有 MDA。 您可以使用應用程式組態設定來啟用特定的 MDA。 您可以在應用程式的組態檔中設定某些個別 MDA 的其他組態設定。 由於載入執行階段時會剖析這些組態檔,因此您必須在受控應用程式啟動之前啟用 MDA。 您無法針對已啟動的應用程式啟用它。

下表列出隨附於 .NET Framework 的 MDA:

MDA
asynchronousThreadAbort (非同步執行緒終止)
bindingFailure
callbackOnCollectedDelegate
contextSwitchDeadlock (上下文切換死鎖)
危险线程API
dateTimeInvalidLocalFormat
dirtyCastAndCallOnInterface
斷開連接的上下文
dllMainReturnsFalse
從Com呼叫時異常被忽略
品質檢查失敗
fatalExecutionEngineError (執行引擎致命錯誤)
gcManagedToUnmanaged
gcUnmanagedToManaged
illegalPrepareConstrainedRegion
無效的公寓狀態變更
無效的CER呼叫
invalidFunctionPointerInDelegate
invalidGCHandleCookie
invalidIUnknown
無效成員宣告
無效重疊調用於Pinvoke
無效變體
jitCompilationStart
loaderLock
loadFromContext
marshalCleanupError
封送處理
成員信息緩存創建
moduloObjectHashcode
nonComVisibleBaseClass
notMarshalable
openGenericCERCall
overlappedFreeError
pInvokeLog
pInvokeStackImbalance
raceOnRCWCleanup
重新進入
releaseHandleFailed
reportAvOnComRelease
streamWriter緩衝資料丟失
virtualCERCall

根據預設,.NET Framework 會為所有 Managed 調試程式啟用 MDA 的子集。 在 Visual Studio 中,您可以在 [偵錯] 功能表上選擇 [Windows>例外狀況設定],然後展開 [受控偵錯助理] 清單,以檢視預設集。

Visual Studio 中的 [例外狀況設定] 視窗

啟用和停用 MDA

您可以使用登錄機碼、環境變數和應用程式組態設定來啟用和停用 MDA。 您必須啟用登錄機碼或環境變數,才能使用應用程式組態設定。

小提示

與其停用 MDA,您可以防止 Visual Studio 每次收到 MDA 通知時顯示 MDA 對話方塊。 若要這樣做,請選擇 [Windows>例外狀況設定],在 [偵錯] 功能表上展開 [受控偵錯輔助工具] 清單,然後選取或清除 [擲回時中斷] 複選框,用於個別 MDA。

登錄機碼

若要啟用 MDA,請在 Windows 登錄中新增HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\MDA子機碼(類型 REG_SZ ,值 1)。 將下列範例複製到名為 MDAEnable.reg 的文字檔。開啟 Windows 註冊表編輯器 (RegEdit.exe),然後從 [ 檔案 ] 選單選擇 [ 匯入]。 選取 MDAEnable.reg 檔案,以在該電腦上啟用 MDA。 將子機碼設定為字串值 1 (不是 DWORD 值 1) 可讓您從 ApplicationName.suffix.mda.config 檔案讀取 MDA 設定。 例如,記事本的 MDA 組態檔會命名為 notepad.exe.mda.config。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
"MDA"="1"

如果計算機在 64 位作系統上執行 32 位應用程式,則應該設定 MDA 金鑰,如下所示:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework]
"MDA"="1"

如需詳細資訊 ,請參閱Application-Specific 組態設定COMPLUS_MDA 環境變數可以覆寫登錄設定。 如需詳細資訊,請參閱 環境變數

若要停用 MDA,請使用 Windows 登錄編輯器將 MDA 子機碼設定為 0 (零)。

根據預設,當您執行附加至調試程式的應用程式時,即使未新增登錄機碼,也會啟用某些 MDA。 您可以執行本節稍早所述的 MDADisable.reg 檔案來停用這些小幫手。

環境變數

MDA 的啟動也可以由環境變數控制,環境變數COMPLUS_MDA會覆寫登錄機碼。 此 COMPLUS_MDA 字串不區分大小寫、以分號分隔的 MDA 名稱清單或其他特殊控制字串。 從 Managed 或 Unmanaged 調試程式開始,預設會啟用一組 MDA。 這可以藉著隱式地將在除錯器下默認啟用的分號分隔的 MDA 清單,添加到環境變數或登錄機碼的值來完成。 特殊控制字串如下:

  • 0 - 停用所有 MDA。

  • 1 - 從 ApplicationName.mda.config讀取 MDA 設定。

  • managedDebugger - 在調試程式下啟動 Managed 可執行檔時,明確啟動隱含啟動的所有 MDA。

  • unmanagedDebugger - 明確啟動所有在使用偵錯工具下啟動 Unmanaged 執行檔時隱含啟動的 MDA。

如果有衝突的設定,最新的設定會覆蓋先前的設定。

  • COMPLUS_MDA=0 會停用所有 MDA,包括調試程式下隱含啟用的 MDA。

  • COMPLUS_MDA=gcUnmanagedToManaged 除了在除錯程式下隱含啟用的任何 MDA 之外,還啟用 gcUnmanagedToManaged

  • COMPLUS_MDA=0;gcUnmanagedToManaged 會啟用 gcUnmanagedToManaged ,但會停用在偵錯工具下隱含啟用的 MDA。

Application-Specific 組態設定

您可以在應用程式的 MDA 組態檔中個別啟用、停用及設定某些助理。 若要啟用應用程式組態檔來設定 MDA,必須設定 MDA 登錄機碼或 COMPLUS_MDA 環境變數。 應用程式組態檔通常位於與應用程式可執行檔 (.exe) 檔案相同的目錄中。 檔案名的格式為 ApplicationName.mda.config;例如,notepad.exe.mda.config。在應用程式組態檔中啟用的助理可能會有屬性或元素,其設計目的是要控制該小幫手的行為。

以下範例展示如何啟用並設定封送處理

<mdaConfig>
  <assistants>
    <marshaling>
      <methodFilter>
        <match name="*"/>
      </methodFilter>
      <fieldFilter>
        <match name="*"/>
      </fieldFilter>
    </marshaling>
  </assistants>
</mdaConfig>

Marshaling MDA 會針對應用程式中每個 Managed 到 Unmanaged 轉換發出要封送至 Unmanaged 類型的 Managed 類型相關信息。 Marshaling MDA 也可以分別篩選 methodFilterfieldFilter 子元素中提供的方法和結構字段名稱。

下列範例示範如何使用預設設定來啟用多個 MDA:

<mdaConfig>
  <assistants>
    <illegalPrepareConstrainedRegion />
    <invalidCERCall />
    <openGenericCERCall />
    <virtualCERCall />
  </assistants>
</mdaConfig>

這很重要

當您在組態檔中指定多個助理時,必須依字母順序列出它們。 例如,如果您想要同時啟用virtualCERCallinvalidCERCall一致MDA,則必須在添加<invalidCERCall />條目之前添加<virtualCERCall />條目。 如果專案不是依字母順序排列,則會顯示未處理的無效組態檔例外狀況訊息。

MDA 例外狀況

啟用 MDA 時,即使程式代碼未在調試程式下執行,它仍為作用中。 如果調試程式不存在時引發 MDA 事件,事件訊息會顯示在未處理的例外狀況對話方塊中,但不是未處理的例外狀況。 若要避免對話框,請在程式代碼未在偵錯環境中執行時,移除啟用 MDA 的設定。

當您的程式代碼在 Visual Studio 集成開發環境 (IDE) 中執行時,您可以避免針對特定 MDA 事件出現的例外狀況對話方塊。 若要這樣做,請在 [ 偵錯] 功能表上,選擇 [Windows>例外狀況設定]。 在 [ 例外狀況設定 ] 視窗中,展開 [ Managed 偵錯小幫手 ] 列表,然後清除個別 MDA 的 [擲回時中斷] 複選框。 您也可以使用此對話框來 啟用 MDA 例外狀況對話框的顯示。

MDA 輸出

MDA 輸出類似於下列範例,其中顯示來自 MDA 的 PInvokeStackImbalance 輸出:

呼叫 PInvoke 函式 'MDATest, MDATest.Program::StdCall' 造成堆疊不平衡。 這可能是因為受管理的 PInvoke 簽章不符合非受管理的目標簽章。 檢查 PInvoke 簽名的呼叫約定和參數是否與目標非管理簽名相匹配。

另請參閱