共用方式為


偵錯時從 .NET 元件產生原始程式碼

當您偵錯 .NET 應用程式時,您可能會發現您想要檢視您沒有的原始程式碼。 例如,在例外狀況時中斷或使用呼叫堆疊跳轉至源位置。

注意

  • 原始碼產生(反編譯)僅適用於 .NET 應用程式,且是以開放原始碼 ILSpy 項目為基礎。
  • 反編譯僅適用於Visual Studio 2019 16.5和更新版本。
  • SuppressIldasmAttribute 屬性套用至元件或模組,可防止 Visual Studio 嘗試反編譯。 雖然 .NET 6 和更新版本中的屬性已經過時,但 Visual Studio 仍舊支援該屬性。

產生原始程式碼

當您進行偵錯且沒有原始碼可用時,Visual Studio 會顯示 原始碼未找到 檔,或如果您沒有元件的符號,則顯示 沒有載入符號 檔。 這兩份檔都有 反編譯原始程式碼 選項,可產生目前位置的 C# 程式代碼。 然後,產生的 C# 程式代碼就如同任何其他原始程式碼一樣使用。 您可以檢視程式代碼、檢查變數、設定斷點等等。

未載入符號

下圖顯示 未載入符號 訊息。

未載入符號檔的螢幕快照

找不到來源

下圖顯示如下 找不到來源 提示訊息。

找不到來源檔的螢幕快照

自動反編譯代碼

從 Visual Studio 2022 17.7 版開始,Visual Studio 調試程式支援自動編譯外部 .NET 程式代碼。 您可以在進入外部程式碼或使用 [呼叫堆疊] 視窗時自動反編譯。

如果您進入已在外部實作的代碼,調試程式會自動將它反編譯,並顯示目前的執行點。 如果您要逐步執行外部程式碼,請停用 Just My Code

您可以從 [呼叫堆疊] 視窗進行反編譯,不必停用 Just My Code。

若要從 [呼叫堆疊] 視窗自動反編譯:

  1. 開啟 [呼叫堆疊] 視窗進行偵錯時,請選擇 [顯示外部程式碼]

  2. 在 [呼叫堆疊] 視窗中,雙擊任何堆疊框架。 調試程式會分解程式代碼,然後直接巡覽至目前的執行點。

    顯示外部程式代碼的 [呼叫堆疊] 視窗螢幕快照。

    所有反編譯程序代碼也會顯示在 [方案總管] 的 [外部來源] 節點底下,以方便視需要流覽外部檔案。

    顯示已反編譯程式集的 [外部來源] 節點螢幕快照。

    您可以偵錯反編譯的程式代碼並設定斷點。

若要停用外部程式代碼的自動反編譯,請移至 [工具] > [選項] > [偵錯] > [一般],然後取消選取 [視需要自動反編譯來源(僅限管理)]

為裝配生成和內嵌資源

除了針對特定位置產生原始程式碼之外,您還可以為指定的 .NET 元件產生所有原始程式碼。 若要執行這項工作,請移至 [模組] 視窗,然後從 .NET 元件的操作功能表中,選取 [[反編譯來源至符號檔] 命令。 Visual Studio 會產生元件的符號檔,然後將來源內嵌至符號檔。 在稍後的步驟中,您可以 擷取內嵌原始程式碼

模組視窗中元件操作功能表的螢幕快照,其中含有反編譯來源命令。

擷取並檢視內嵌原始程式碼

您可以在 模組 視窗的操作功能表中,使用 [擷取原始程式碼] 命令,來擷取內嵌於符號檔中的原始程式檔。

具有擷取來源命令之模組視窗中元件操作功能表的螢幕快照。

擷取的來源檔案會以雜項檔案形式新增至方案。 Visual Studio 預設會關閉其他檔案功能。 您可以從 [工具]>[選項]>[環境]>[檔]>[在方案總管 中顯示其他檔案] 複選框啟用此功能。 如果未啟用此功能,則無法開啟擷取的原始程式碼。

已啟用其他檔案選項的工具選項頁面螢幕快照。

擷取的來源檔案會出現在 方案總管的其他檔案中

包含其他檔案的方案總管螢幕快照。

針對啟用 SourceLink 的 .NET 程式庫或 NuGet 套件,您也可以進入原始碼、設定斷點,並使用所有偵錯工具的功能。 如需詳細資訊,請參閱 使用 Source Link 啟用偵錯和診斷,使用 SourceLink改善偵錯時間生產力。

已知限制

需要中斷模式

只有在調試程式處於中斷模式且應用程式暫停時,才能使用反編譯產生原始程式碼。 例如,當 Visual Studio 遇到斷點或例外時,會進入中斷模式。 您可以使用 Break All 命令,輕鬆地讓 Visual Studio 在下次程式碼運行時暫停(中斷所有圖示)。

反編譯限制

從 .NET 元件中使用的中繼格式 (IL) 產生原始程式碼具有一些固有的限制。 因此,產生的原始碼看起來不像原始原始程式碼。 大部分的差異位於運行時不需要原始碼資訊的部分。 例如,運行時間不需要空格符、批注和局部變數名稱等資訊。 我們建議您使用生成的源代碼來瞭解程序的執行方式,而不是取代原始程式碼。

對優化或發行組件進行偵錯

當偵錯由使用編譯程式優化所編譯的組件反編譯出的程式碼時,您可能會遇到下列問題:

  • 斷點不一定會綁定到對應的來源位置。
  • 執行逐步操作時,可能無法總是到達正確的位置。
  • 局部變數可能沒有正確的名稱。
  • 某些變數可能無法用於評估。

您可以在 GitHub 問題中找到更多詳細數據:ICSharpCode.Decompiler 與 VS Debugger 整合

反編譯可靠性

反編譯嘗試的相對較少百分比可能會導致失敗。 此行為是因為 ILSpy 中的序列點 Null 參考錯誤所造成。 我們已藉由捕捉這些問題,並優雅地讓反編譯嘗試失敗來減少影響。

您可以在 GitHub 問題中找到更多詳細數據:ICSharpCode.Decompiler 與 VS Debugger 整合

異步程序代碼的限制

使用 async/await 程式代碼模式進行反編譯模組的結果可能不完整或完全失敗。 ILSpy 對於 async/await 和 yield 狀態機的實作僅部分完成。

如需詳細資訊,請參閱 GitHub 問題:PDB 產生器狀態

Just My Code

Just My Code(JMC) 設定可讓 Visual Studio 直接跳過系統、框架、函式庫和其他非使用者呼叫。 在偵錯會話期間,[模組] 視窗會顯示調試程式將哪些程式代碼模組視為 [我的程式碼] (使用者程序代碼)。

優化或發行模組的反編譯會產生非用戶程序代碼。 例如,如果調試器在反編譯的非使用者代碼中中斷,就會顯示 無來源 視窗。 若要停用 Just My Code,請流覽至 Tools>Options (或 Debug>Options>Debug>General,然後取消選取 [啟用 Just My Code ]

擷取的來源

從元件擷取的原始程式碼具有下列限制:

  • 無法設定所產生檔案的名稱和位置。
  • 檔案是暫時的,並由 Visual Studio 刪除。
  • 這些檔案會放在單一資料夾中,而且未使用原始來源的任何資料夾階層。
  • 每個檔案的檔名都包含檔案的總和檢查碼哈希。

產生的程式代碼僅限 C#

反編譯只會在 C# 中產生原始程式碼檔案。 沒有任何選項可以產生任何其他語言的檔案。