偵錯時從 .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。
若要從 [呼叫堆疊] 視窗自動反編譯:
開啟 [呼叫堆疊] 視窗進行偵錯時,請選擇 [顯示外部程式碼]。
在 [呼叫堆疊] 視窗中,雙擊任何堆疊框架。 調試程式會分解程式代碼,然後直接巡覽至目前的執行點。
所有反編譯程序代碼也會顯示在 [方案總管] 的 [外部來源] 節點底下,以方便視需要流覽外部檔案。
您可以偵錯反編譯的程式代碼並設定斷點。
若要停用外部程式代碼的自動反編譯,請移至 [工具] > [選項] > [偵錯] > [一般],然後取消選取 [視需要自動反編譯來源(僅限管理)]。
為裝配生成和內嵌資源
除了針對特定位置產生原始程式碼之外,您還可以為指定的 .NET 元件產生所有原始程式碼。 若要執行這項工作,請移至 [模組] 視窗,然後從 .NET 元件的操作功能表中,選取 [[反編譯來源至符號檔] 命令。 Visual Studio 會產生元件的符號檔,然後將來源內嵌至符號檔。 在稍後的步驟中,您可以 擷取內嵌原始程式碼。
擷取並檢視內嵌原始程式碼
您可以在 模組 視窗的操作功能表中,使用 [擷取原始程式碼] 命令,來擷取內嵌於符號檔中的原始程式檔。
擷取的來源檔案會以雜項檔案形式新增至方案。 Visual Studio 預設會關閉其他檔案功能。 您可以從 [工具]>[選項]>[環境]>[檔]>[在方案總管 中顯示其他檔案] 複選框啟用此功能。 如果未啟用此功能,則無法開啟擷取的原始程式碼。
擷取的來源檔案會出現在 方案總管的其他檔案中。
SourceLink
針對啟用 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# 中產生原始程式碼檔案。 沒有任何選項可以產生任何其他語言的檔案。