官方的 dnSpy 在 2021 時,由于某些吃瓜的原因 wtfsck 將 dnSpy 給 Archived 掉,在大佬被哄好之前,預計是不再更新,最新官方版本對 dotnet 6 的支持較弱,對于很多 dotnet 6 應用都無法成功除錯,附加除錯上去將會讓應用卡住,好在 dnSpy 是開源的,也剛好 lsj 大佬改得動,于是改了一個支持 dotnet 6 的版本
什么是 dnSpy 神器?請看 神器如 dnSpy,無需原始碼也能修改 .NET 程式 - walterlv
我現在使用最多的除錯工具,除了 VisualStudio 之外,就是 dnSpy 工具了,使用 dnSpy 可以讓我方便除錯用戶端的應用,在完成了將團隊里面最大的專案升級到 dotnet 6 時,就在升級程序遇到了一些問題,想要除錯,卻發現沒有合適的工具,詳細請看 dotnet 6 在 Win7 系統證書鏈錯誤導致 HttpWebRequest 記憶體泄露
為了讓我減少加班,我請了 lsj 幫忙改改 dnSpy 神器,讓 dnSpy 可以除錯 dotnet 6 的應用
這是支持 dotnet 6 版本的 dnSpy 神器下載地址,也是修改之后開源的地址: https://github.com/kkwpsv/dnSpy/releases/tag/6.1.9
如果大家下載不了,可以發郵件讓我用其他方式發給你
那改好了是不是就完成了?還有一個問題是為什么 dnSpy 對 dotnet 6 的支持較弱呢?有以下幾個原因,對應的修復方法還請看 lsj 的改動 https://github.com/kkwpsv/dnSpy/commit/a217b257453147c5d9db45070f7555f6395329bf
如 [DAC][DBI] ICorDebugModule::GetMetaDataInterface fails in net6.0 for "Anonymously Hosted DynamicMethods Assembly" in unit test project. · Issue #62977 · dotnet/runtime 所說的原因,由于 "Anonymously Hosted DynamicMethods Assembly" 沒有定義 IMetaDataImport2 介面,因此在 https://github.com/dnSpy/dnSpy/blob/2b6dcfaf602fb8ca6462b8b6237fdfc0c74ad994/Extensions/dnSpy.Debugger/dnSpy.Debugger.DotNet.CorDebug/Impl/ModuleCreator.cs#L94-L96 將拿到空,如以下代碼,將拋出 InvalidOperationException 錯誤
var comMetadata = https://www.cnblogs.com/lindexi/archive/2022/09/29/dnModule.CorModule.GetMetaDataInterface();
if (comMetadata is null)
throw new InvalidOperationException();
修復的方式就是不拋出例外,而是自己定義一個 繼承 DmdLazyMetadataBytes 型別的 DmdLazyMetadataBytesNull 型別,進行回傳,如以下代碼
if (comMetadata is null)
// "Anonymously Hosted DynamicMethods Assembly" not implement IMetaDataImport2, we just return DmdLazyMetadataBytesNull
return () => new DmdLazyMetadataBytesNull();
同時在 DmdAppDomainImpl.cs 里面,回傳 DmdNullMetadataReader 即可,如此也許會影響讀取程式集的資訊,但好過無法除錯
這個 "Anonymously Hosted DynamicMethods Assembly" 沒有定義 IMetaDataImport2 介面,也影響 https://github.com/dnSpy/dnSpy/blob/2b6dcfaf602fb8ca6462b8b6237fdfc0c74ad994/Extensions/dnSpy.Debugger/dnSpy.Debugger.DotNet.CorDebug/dndbg/Engine/CorAssembly.cs#L56-L60 的代碼,如以下代碼,拿到的 ManifestModule 是空值,好在這里只是在 dnSpy 應用的 Debug 模式才會炸掉
var module = ManifestModule;
Debug2.Assert(module is not null);
修復的方法只是將 Assert 的代碼干掉即可
經過以上更改,就可以讓 dnSpy 支持 dotnet 6 的除錯
嗯,現在我覺得 dnSpy 作者做的還是太對了,我似乎越來越覺得開源也是一個不對的事情,那就是 SB 太多了,本來今天是想著將 dnSpy 在堆疊網上廣告一下,造福一下國外的小伙伴,可惜遇到了傻比,最后我將問題和回答都洗掉了,這個事讓我更加理解了很多開源作者最后選擇了閉源的做法,以及讓我更加佩服維護社區的大佬們,有人問,原作者關閉了 dnSpy 的瓜是什么?其中一個瓜就是被傻子給氣的,開源了不收錢了,反而被當成理所當然,還要這要那,不滿足了還被罵,具體的瓜還請自己去找了
我認為所有的參與開源和分享知識的行為都理應受到表揚稱贊,共同維護一個良好的開發者生態
十分感謝 wtfsck 大佬提供的 dnSpy 神器,和 lsj 讓 dnSpy 支持 dotnet 6 除錯
博客園博客只做備份,博客發布就不再更新,如果想看最新博客,請到 https://blog.lindexi.com/

本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可,歡迎轉載、使用、重新發布,但務必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用于商業目的,基于本文修改后的作品務必以相同的許可發布,如有任何疑問,請與我[聯系](mailto:[email protected]),
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/509802.html
標籤:.NET技术
