面對刁鑽的 .NET 程式問題,開 Visual Studio 用 F5 Line-By-Line 逐行偵錯是最犀利的破解手段,出錯之前先設定中斷點,按 F10、F11 一步步逼近爆炸中心,配合逐一檢查各變數是否符合預期,通常很快真相就能水落石出。但如果爆炸點在第三方程式庫呢?

如果第三方程式庫為開源專案(Open Source),我們可以從 Github 抓原始碼回來,自行編譯並替換專案參照來源以便深入偵錯。不過,實際下場玩過,你就會體驗到「用說的比較簡單」。有時開源專案要編譯成功,過程還挺坎坷的,例如:需要另外安裝特定的開發工具、Runtime、程式庫(例如:之前 ASP.NET Core 專案需要 .NET 5.0.0-alpha)、有些開源專案龐大到數百 MB 起跳、遇到其他程式庫也引用該程式庫必須處理版本衝突... 等等。總之,取得原始碼編譯這件事想像複雜一點。而更要命的問題是,並不是所有程式庫都是開源的,沒有原始碼可抓。使用 JustDecompile 或 dotPeek 之類的反組譯工具可以一窺邏輯,但沒法線上逐步偵錯總是遺憾。

很多人可能沒發現(包含昨天的我),地表最強的開發工具 Visual Studio 已默默強化第三方程式庫偵錯功能了。從 Visual Studio 2017 15.3+ 起,有個新功能 - Source Link,針對 NuGet 程式庫,允許開發者直接從版控主機(主要是 Github 及 Azure DevOps/VSTS)取回原始碼進行偵錯,前題是 NuGet 程式包需內嵌版控資訊(Soure Control Metadata),一些熱門程式庫例如 Json.NET、Dapper 早早已加入:(可使用 NuGet Package Explorer 檢查 Repository 設定,有 URL 跟 Commit 編號就)

要載入第三方程式庫原始碼偵錯有個前題,需先關閉 Enable Just My Code 選項:

另外,使用 Source Link 前必須先取得 Symbol 檔(.pdb)。要檢查 Symbol 檔是否載入,可在偵錯期間透過 Debug / Windows / Modules 叫出模組清單視窗:

下圖展示兩種狀況,Dapper.dll 已內含 Symbol,所以 Symbol Status 為 Symboles loaded,Symbol File 顯示 Dapper.dll(embedded);Newtonsoft.Json.dll 則是 Cannot find or open the PDB file. 但 Json.NET 的 PDB 可由 NuGet 取得,故我們先設定 Symbol Settings,再按 Load Symbols 可以載入:

注意,在 Symbol Settings 設定,記得勾選 NuGet.org Symbol Server,按下 Load Symbols 時,若 NuGet 程式庫有另外提供 PDB,Visual Studio 將自動取得:

確認支援 Source Link 的 NuGet 程式庫都載入 Symbol 後,若在程式庫內部發生錯誤,或按 F11 Step Into 要進入程式庫函式,Visual Studio 將提示是否下載原始碼:

然後,不知不覺我們的偵錯行數已跑進第三方程式庫的原始碼囉:

如果程式不是來自 NuGet 或不是開源專案怎麼辦,Visual Studio 2019 在 16.5 版之後再加入一個更強大的功能 - 即時將 DLL 反組譯成 C#。

Modules 視窗選單有個 Decompile Source to Symbol File:

或出錯時,由 Call Stack 視窗開啟 Frame 資訊頁選 Decompile source code:

反組譯前 Visual Studio 會提醒不要違反軟體授權相關規定:

就醬,咻一聲,我們已滑進 Visual Studio 反組譯產生的 C# 原始碼囉~

這些反組譯的 .cs 程式碼會放在 Miscellaneous Files 資料夾,從 Options / Environment / Document 可切換要不要顯示在 Solution Explorer:

Miscellaneous Files 預設只會顯示目前在 IDE 開啟中的雜項檔案,Items saved in the Miscellaneous files project 可指定保留最近幾筆開啟過的檔案項目。

Tips of how to use Source Link and decompilation feature of Visual Studio to debug 3rd party library.


Comments

# by 陳大胖

請問 Decompile Source to Symbol File 這功能該如何開啟? 我的VS2019這選項都是灰色,不能使用。

# by Jeffrey

to 陳大胖,我查到以下案例:https://developercommunity.visualstudio.com/t/decompile-source-code-not-listed-visible/1181438#T-N1189268 The command is still available by right clicking on a module in the Modules window, however the name of the command is "Decompile Source to Symbol File". If you application is running (not in break mode), the command should still be visible but disabled. In order to invoke the command, please have the debugger break using the Break All command.

# by 陳大胖

to Jeffrey : 非常感謝您的回答,的確如上所說,只要按Break All指令,該功能即可啟動,心感恩。

# by Victor Tseng

路過順便分享一點心得,Decompile Source to Symbol File 這招如果目標 dll 參照了 non-managed 的 dll (例如 log4net.dll 參照了 advapi32.dll),看起來就會無法反組譯。

Post a comment