在我國自動化控制領域應用較廣泛的工業自動化組態軟體有Wonderware公司InTouch、西門子公司Wincc、GE公司iFix。國內也有一些傳統組態軟體廠商,使用的功能和形式基本上十分類似,受當時開發環境和組態軟體框架的限制,也很難做較大的改變。 ...
應用程式如果啟動即閃退,那大部分時候日誌模塊還沒初始化完成,很難通過應用自身的啟動流程瞭解到應用啟動失敗的原因。本文來告訴幾個不同的方法用來調查應用啟動失敗的原因
應用啟動失敗的原因可能有很多,例如系統環境問題,例如寫個點逗比代碼,例如調用某個帶毒的庫。如果應用啟動失敗,可以在開發環境上復現,那無疑是十分好的事情,因為咱可以使用開發環境強大的 VisualStudio 調試工具進行調試
使用 VisualStudio 調試應用啟動失敗
在有符號的配合下,使用 VisualStudio 定位應用軟體啟動失敗在大多數時候都是比較輕鬆的。當然,沒有符號的話,也沒多少問題,至少可以快速定位到是哪個模塊
使用 VisualStudio 定位應用軟體啟動失敗的方法是讓 VisualStudio 啟動應用且進入調試模式。做法就是隨便找一個 dotnet 6 的項目,當然,如果是所要調試的應用的對應版本的代碼的項目那是最好的。點擊設置調試屬性,設置應用作為啟動路徑
在 VisualStudio 2022 下,打開設置調試屬性的界面可以是在項目上進行右擊,然後點擊屬性,找到調試頁面,點擊打開調試啟動配置文件即可看到,如下圖
接著點擊創建新配置文件,選擇可執行文件
接下來選擇需要調試啟動失敗的應用的路徑
為了同時捕獲一些本機異常,還請勾選“啟用本機代碼調試”也就是混合調試模式。本機異常包括 Window Runtime 拋出的異常,基礎的 Win32 調用包含的非返回值的錯誤的異常,以及外部 C++ 等庫的異常等
為了提升調試的成功率,還請在 VisualStudio 設置裡面,將所有的異常都打開進行捕獲,同時關閉僅我的代碼調試。打開所有異常捕獲的方法是在 調試->視窗->異常設置 裡面進行配置。簡單來說就是將能打鉤的全部打上,當然,你要是熟悉的話,那就少打鉤一些咯,反正多打鉤也沒啥問題
關閉僅我的代碼可以讓你調試到一些被優化的代碼。在咱 dotnet 的程式集裡面,對 Debug 下和 Release 下最大的不同在於勾選了優化代碼。如果勾選了僅我的代碼調試,那將只調試 Debug 生成的程式集,而預設忽略對 Release 的程式集的記錄。在大部分的調試下,這個模式都可以減少發佈的程式集的干擾,可以更加方便調試業務代碼。但是當前是在調試啟動失敗,啟動失敗可能是庫的鍋,需要調試發佈的程式集,推薦關閉僅我的代碼調試。關閉的方法是在 VisualStudio 的 工具-> 選項 -> 調試 裡面,去掉 啟用“僅我的代碼” 的選項
完成配置之後,在 VisualStudio 裡面,選擇剛纔創建的新配置作為啟動項進行啟動
推薦是第一次調試可以快速過,看看是不是有異常觸發,逐步去掉那些不影響啟動異常的干擾,嘗試找到導致啟動失敗的異常,即可進行快速定位
而啟動失敗還有一個隱藏的原因是寫了逗比代碼,自己退出的。那就需要自己進行調試,找到是哪個模塊退出了應用,可以在第一次調試的時候,通過輸出視窗找到應用的退出碼是多少,輔助定位邏輯。如果退出碼是一個零,那找找是不是存在 Environment.Exit(0);
類似的代碼,可以全局進行字元串查找對應的代碼。或者是 Main 函數執行完成,例如在 WPF 裡面調用了 Application.Current.Shutdown
進行退出
在開發環境上遇到應用啟動失敗,大部分時候都可以在 VisualStudio 的幫助下快速定位到為什麼啟動失敗
但是如果應用只是在用戶的設備上才失敗,那就沒那麼好玩了,接下來將告訴大家如何調試用戶端的應用啟動失敗
使用 dnSpy 調試應用啟動失敗
在用戶的設備上,如果應用啟動失敗了,如果此時應用自己的日誌模塊還沒初始化完成,那也不用慌,系統的事件查看器可能可以幫忙到你。打開系統的事件查看器,裡面也許記錄了一些應用啟動失敗的原因,例如是系統環境問題,比如是系統缺少了某個庫,或者是驅動問題。我之前很經常遇到的就是 WPF 應用啟動失敗是由顯卡驅動導致的,不過顯卡驅動問題基本上用不到多少的調試,稍微看一下就能看到了,系統的各個部分都會很奇怪
如何打開系統的事件查看器?在 Win10 下,右擊開始菜單按鈕,點擊事件查看器即可打開。打開之後,大部分時候都可以先去看 Windows 日誌裡面的應用程式的日誌,裡面也許有記錄應用的啟動失敗原因
但是有時候事件查看器記錄的也很迷,如下麵例子的啟動失敗的記錄
系統記錄了兩條相關的錯誤日誌,一條是 .NET Runtime 錯誤日誌,如下內容
Application: KajijuniLiguqujokemka.exe
CoreCLR Version: 6.0.522.21309
.NET Version: 6.0.5
Description: The process was terminated due to an internal error in the .NET Runtime at IP 00007FF9DAEBDA03 (00007FF9DACF0000) with exit code c0000005.
另一條是 Application Error 日誌,內容如下
錯誤應用程式名稱: KajijuniLiguqujokemka.exe,版本: 1.0.0.0,時間戳: 0x62571213
錯誤模塊名稱: coreclr.dll,版本: 6.0.522.21309,時間戳: 0x625708f4
異常代碼: 0xc0000005
錯誤偏移量: 0x00000000001cda03
錯誤進程 ID: 0x3814
錯誤應用程式啟動時間: 0x01d882fdfe019fc7
錯誤應用程式路徑: C:\lindexi\Code\lindexi\BeyajaydahifallChecheecaifelwarlerenel\KajijuniLiguqujokemka\bin\Debug\net6.0-windows\KajijuniLiguqujokemka.exe
錯誤模塊路徑: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.5\coreclr.dll
報告 ID: 45232171-a61e-46fa-b80b-248ad12f5fef
錯誤程式包全名:
錯誤程式包相對應用程式 ID:
這兩條日誌沒有能給咱很好的一個調試思路,只能說明應用確實掛了而已。不能說明是應用自己寫了逗比代碼,也不能證明是系統環境問題,也不能證明是調用庫的問題。想要瞭解為什麼,只能繼續往下進行調試
通過 dnSpy 神器可以輔助在用戶端進行調試。根本原因在於 VisualStudio 太龐大了,在用戶端安裝不太現實。但 dnSpy 是非常輕巧的,可以免安裝使用。相當於在用戶端跑一個輕巧的 VisualStudio 調試工具
支持 dotnet 6 版本的 dnSpy 下載地址請看 支持 dotnet 6 的 dnSpy 神器版本
調試的思路和上文的使用 VisuslStudio 調試的差不多,有稍微一點不同的是,需要先將要調試的 Exe 拖入到 dnSpy 中,然後點擊此 Exe 進行調試。同樣需要勾選異常等
使用 dnSpy 調試還有一個好處是,可以無須任何符號即可進行調試,十分方便
使用 ProcDump 進行 DUMP 分析
但是如果應用的啟動失敗不是每次都復現的,是概率復現的,那就不好玩了。以上兩個方法都是需要進行調試啟動的,而大家都知道,調試模式下和非調試模式下是有差別的,例如多線程執行的差別。如果剛好啟動是因為線程安全導致的問題,那麼調試下也許是復現不到的。對於不是每次都失敗的應用啟動,進行調試是非常想砸鍵盤的,有時候調試的好好的,應用就啟動成功了。有時候覺得沒問題,按下繼續,應用就啟動失敗了
或者是在用戶端,用戶有情緒了,不適合進行慢慢的調試。此時可以用到 ProcDump 工具輔助,在應用啟動時候的時候,將失敗時做一個 DUMP 文件,然後咱就可以將這個 DUMP 傳回開發的設備上慢慢進行分析
這個 ProcDump 是微軟極品工具箱的一個很有名的工具
官方下載地址: https://docs.microsoft.com/zh-cn/sysinternals/downloads/procdump
根據官方文檔可以瞭解到使用方法是在命令行使用如下參數,即可做到在應用因為異常掛掉自動捕獲 DUMP 文件
procdump.exe -e -t -w -ma <進程名>
參數的含義如下
-e
: 當進程遇到未經處理的異常時寫入轉儲-t
: 進程終止時寫入轉儲。如果應用啟動失敗是自己逗比或者某個庫逗比調用了退出進程的方法,那也可以使用捕獲到-w
: 等待指定的進程啟動。大部分時候都是先運行 ProcDump 工具,然後再啟動應用,這樣 ProcDump 相當於監控應用啟動失敗或退出。如此即可採用 ProcDump 啟動進程調試應用啟動閃退-ma
: 獲取的是 Full Dump 文件,也就是包含所有內容的 DUMP 文件,雖然這個 DUMP 比較大,但是調試會根據方便。如果傳輸過程比較難,而且開發者也熟悉調試 DUMP 可以換用-mm
命名寫入小型 DUMP 文件
假定需要調試的啟動失敗的應用是 KajijuniLiguqujokemka.exe
應用,那麼執行的命令如下
procdump.exe -e -t -w -ma KajijuniLiguqujokemka
如此即可在應用啟動閃退自動創建 DUMP 文件。創建好的 DUMP 文件可以採用 7z 工具壓縮一下再傳回開發機器,使用 7z 可以極大壓縮 DUMP 文件,因為 DUMP 文件裡面很多數據都是全 0 的
拿到 DUMP 文件之後,就需要開啟 DUMP 調試了。最簡單的 DUMP 調試是打開 VisualStudio 將 DUMP 文件拖進入,然後如開始的步驟先配置一下,然後點擊使用混合進行調試即可
核心是看調用堆棧,和局部變數視窗,找到是哪個模塊拋出異常或者退出。如果 VisualStudio 無法幫到你,那就只能換成 WinDbg 啦,不過這又是另外一個故事了
大家可以嘗試使用我放在 github 的代碼進行測試
更多請看 dotnet 代碼調試方法
博客園博客只做備份,博客發佈就不再更新,如果想看最新博客,請到 https://blog.lindexi.com/
本作品採用知識共用署名-非商業性使用-相同方式共用 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發佈,但務必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我[聯繫](mailto:[email protected])。