使用受控偵錯助理診斷錯誤

受控偵錯助理 (MDA) 是偵錯輔助程式,可使用 Common Language Runtime (CLR) 提供執行階段狀態的相關資訊。 這些助理會產生有關您無法設陷之執行階段事件的告知性訊息。 您可以使用 MDA 來隔離在 Managed 與 Unmanaged 程式碼之間轉換時,所發生之不易發現的應用程式 Bug。

您可以啟用或停用所有 MDA,方法為將一個機碼新增至 Windows 登錄或設定環境變數。 若要啟用特定 MDA,您可以使用應用程式組態設定。 您可以針對應用程式組態檔中某些個別的 MDA,設定額外的組態設定。 因為在載入執行階段時,會剖析這些組態檔,所以您必須在 Managed 應用程式啟動之前,先啟用 MDA。 您不能為已啟動的應用程式啟用 MDA。

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

MDA
asynchronousThreadAbort
bindingFailure
callbackOnCollectedDelegate
contextSwitchDeadlock
dangerousThreadingAPI
dateTimeInvalidLocalFormat
dirtyCastAndCallOnInterface
disconnectedContext
dllMainReturnsFalse
exceptionSwallowedOnCallFromCom
failedQI
fatalExecutionEngineError
gcManagedToUnmanaged
gcUnmanagedToManaged
illegalPrepareConstrainedRegion
invalidApartmentStateChange
invalidCERCall
invalidFunctionPointerInDelegate
invalidGCHandleCookie
invalidIUnknown
invalidMemberDeclaration
invalidOverlappedToPinvoke
invalidVariant
jitCompilationStart
loaderLock
loadFromContext
marshalCleanupError
marshaling
memberInfoCacheCreation
moduloObjectHashcode
nonComVisibleBaseClass
notMarshalable
openGenericCERCall
overlappedFreeError
pInvokeLog
pInvokeStackImbalance
raceOnRCWCleanup
reentrancy
releaseHandleFailed
reportAvOnComRelease
streamWriterBufferedDataLost
virtualCERCall

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

Exception Settings window in Visual Studio

啟用和停用 MDA

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

提示

您可以防止 Visual Studio 每當收到 MDA 通知時就顯示 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"

如需詳細資訊,請參閱應用程式特定組態設定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 會啟用 gcUnmanagedToManaged,以及在偵錯工具之下隱含啟用的任何 MDA。

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

應用程式特定組態設定

您可以針對該應用程式,在 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 會針對應用程式中的每個受控至非受控轉換,發出封送處理至非受控類型的受控類型相關資訊。 Marshaling MDA 也可以分別篩選 methodFilterfieldFilter 子項目中提供的方法和結構欄位名稱。

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

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

重要

當您在組態檔中指定多個助理時,必須依字母順序將其列出。 例如,如果您想要啟用 virtualCERCallinvalidCERCall MDA ,則必須在 <invalidCERCall /> 項目前面加入 <virtualCERCall /> 項目。 如果這些項目沒有依照字母順序,就會顯示未處理的無效組態檔例外狀況訊息。

MDA 例外狀況

當 MDA 啟用時,即使您的程式碼不是在偵錯工具下執行,MDA 仍作用中。 如果在偵錯工具不存在的情況下,發生 MDA 事件,則會在未處理的例外狀況對話方塊中顯示事件訊息,雖然 MDA 事件並不是未處理的例外狀況。 若要避免此對話方塊,請在程式碼不是在偵錯環境中執行時,移除啟用 MDA 的設定。

當您的程式碼在 Visual Studio 整合式開發環境 (IDE) 中執行時,您可以避免因特定 MDA 事件而出現的例外狀況對話方塊。 若要這樣做,請在 [偵錯] 功能表上,選擇 [Windows]>[例外狀況設定]。 在 [例外狀況設定] 視窗中,展開 [受控偵錯助理] 清單,然後針對個別的 MDA 清除 [擲回時中斷] 核取方塊。 您也可以使用這個對話方塊來「啟用」 MDA 例外狀況對話方塊的顯示。

MDA 輸出

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

呼叫 PInvoke 函式 'MDATest!MDATest.Program::StdCall' 讓堆疊失去了平衡。 這可能是因為受控 PInvoke 簽章不符合非受控目標籤章。 檢查 PInvoke 簽章的呼叫慣例和參數是否符合目標非受控簽章。

另請參閱