Windows 除錯工具課程

lindexi發表於2024-09-19

本文是我在集團內部上的課程記錄而成的部落格內容。在本次課程裡面將和大家介紹一些在 Windows 上常用的除錯工具,以及調查問題的常見套路。適合於夥伴們入門 Windows 除錯

本文以下內容是採用原本課程課件裡面的一頁頁的內容組裝而來,過程中補充一些講課時的內容

本次課程裡面核心的內容是除錯工具,除錯工具是我們在除錯軟體的時候的利器,透過除錯工具我們可以找到軟體的問題,解決軟體的問題

本次的課程的開始我來和大家講一個除錯故事,這個故事是從使用者反饋軟體用不了的問題開始的

使用者說軟體用不了,那可能會是什麼問題呢?使用者不是專業的開發人員,他們不知道如何準確的表述問題

學過軟體工程的同學應該有不少,軟體工程裡面應該會有提到,開發的第一步也是非常關鍵的一步就是需求分析。當收到使用者反饋說軟體用不了時,使用者在說什麼呢?是不是可能是軟體崩潰了?還是軟體無法啟動?還是其他的問題

遇到使用者說軟體用不了的時候,咱可以有哪些入手點呢?我的調查思路是分為兩個大的方向。第一個方向是從當下的情況入手。如果當下已經沒有了現場了,則可以考慮第二個方向,復現(重現)問題

從第一個方向入手時,可以先考慮從使用者的裝置上尋找痕跡。接下來我將和大家聊聊如何開始從使用者的裝置上尋找痕跡。當然了,如果這個使用者是咱的測試人員或者是咱的同事,那尋找痕跡這一步就更有價值了

在使用者裝置上尋找痕跡時,別忘了 Windows 是咱的好朋友。Windows 提供了很多工具,可以幫助我們找到問題的原因。接下來我將和大家介紹一些 Windows 上自帶的常用的除錯工具

第一站就是事件檢視器。可以先假設咱可能遇到的是軟體啟動即崩潰的問題。在不遠端使用者的情況下,可以先請使用者傳送系統事件日誌或截圖過來看看。事件檢視器作為第一站的原因是可不發起遠端,直接請使用者截圖或傳送日誌過來。相對來說對開發者的工作成本較低

透過事件檢視器可以進行快速的分析,如看到軟體崩的日誌,那就可以證明確實是軟體崩潰了。後續咱的調查方向就可以向著軟體崩掉的方向進行

也有可能透過事件檢視器直接看到非常有效的資訊,直接就結束戰鬥,定位到了問題

舉個例子

有一次我在除錯一個軟體的時候,使用者反饋說軟體無法啟動。我讓使用者傳送了事件檢視器的日誌過來,透過日誌可以看到如下內容

錯誤應用程式名稱: lindexi.exe,版本: 5.1.12.63002,時間戳: 0xedd2d687
錯誤模組名稱: MSVCR100.dll,版本: 10.0.40219.325,時間戳: 0x4df2be1e
異常程式碼: 0x40000015
錯誤偏移量: 0x0008d6fd
錯誤程序 ID: 0x994
錯誤應用程式啟動時間: 0x01d50ac3bd970061
錯誤應用程式路徑: C:\Program Files\lindexi\lindexi.exe
錯誤模組路徑: C:\Program Files\PowerShadow\App\MSVCR100.dll
報告 ID: a0c5c0b1-76b7-11e9-9d20-94c69123de40

細心的夥伴也許一眼就看出來問題了,出現問題的是 MSVCR100.dll 模組,然而這個模組路徑居然是在一個不認識的,名為 PowerShadow 的軟體的目錄下。這時候就可以大概確定問題了,這是被投毒了

試試用谷歌好幫手,搜搜這個軟體是什麼軟體。剛好搜到了這篇部落格: 影子系統讓 C++ 程式無法執行

於是這就結束戰鬥了,調查到了問題的原因,軟體無法啟動是因為被投毒了,被影子系統投毒了。解決方法就是請使用者解除安裝影子系統,因為影子系統也不維護了,咱軟體層沒啥好掙扎的

可惜的是在很多使用者的裝置上,事件檢視器日常不工作。沒關係,能從事件檢視器找到額外資訊,就是賺到了

如果事件檢視器找不到或不能用?咱還有其他很多工具可以用

尋找痕跡的時候,另一個常用的好工具就是工作管理員。工作管理員是 Windows 自帶的一個工具,可以幫助我們瞭解到非常多的資訊

透過工作管理員尋找痕跡時,可以按照如上圖所示的決策樹瞭解一下情況。如果不能在工作管理員裡面看到程序,那很可能就是程序已經崩掉了。如果能夠看到程序,那可能就是程序卡了。此時關注點可以是 CPU 使用率。如果 CPU 使用率不動,那可以猜猜可能是死鎖問題,如果 CPU 使用率爆高,那可能是死迴圈等問題。同步也看一下記憶體使用率,雖然在工作管理員裡面看記憶體使用率不能真實反映記憶體使用情況,但是可以作為一個參考。詳細關於如何正確檢視程式的記憶體使用情況,後面會有專門的內容介紹

無論是何種情況,都可以試試撈一個 DUMP 回來除錯看看。當然了,對於軟體崩掉的情況,先嚐試一下是不是能啟動起來,拼手的速度快速撈一個 DUMP 回來,如果不能,那後文還會和大家介紹其他工具來輔助撈 DUMP 檔案

先回顧一下,咱的調查思路一開始就是嘗試尋找痕跡。尋找痕跡的時候藉助 Windows 裡面提供的好用的工具,這裡重點介紹的是事件檢視器和工作管理員。透過事件檢視器可以快速的瞭解到軟體崩潰的原因,透過工作管理員可以瞭解到軟體的執行情況

在透過自帶的工具沒有明確收穫的情況下,則嘗試撈一個 DUMP 回來開發機器上進行進一步分析

本課程這裡提到的 DUMP 檔案是指 Windows 下的記憶體轉儲檔案,是一個二進位制檔案,簡單用人話說就是將程序的記憶體內容儲存到檔案裡面。透過 DUMP 檔案可以有效還原出此時的程序的記憶體狀態和記憶體裡面的內容,可以用於進一步的分析。當使用者環境裡面沒有帶開發工具時,撈一個 DUMP 檔案回來,可以幫助我們在開發機器上進行進一步的分析。撈 DUMP 分析的過程,相當於給程序做了一個快照,然後將其放在開發機器上進行進一步的分析

假設程序還在的話,那最簡單的撈 DUMP 方式就是透過工作管理員右鍵選擇建立記憶體轉儲檔案了。對應的英文系統是 Create memory dump file 選單項

這裡需要額外說明的是,如果當前系統是 x64 系統,但是自己的程序是 x86 程序,那此時不建議使用預設開啟的工作管理員撈 DUMP 檔案。因為預設開啟的工作管理員是 x64 的,打出來的是 x64 轉儲檔案,包含 WoW64 子系統的資訊。詳細請看 你生成的轉儲檔案有問題嗎? - 知乎

正確的做法應該是使用 C:\Windows\SysWOW64\Taskmgr.exe 的工作管理員去撈 DUMP 檔案

現在假定撈到了 DUMP 檔案了,那接下來的步驟就是如何分析 DUMP 檔案了。當然了,前置步驟就是如何將 DUMP 檔案傳回到自己的開發機器上,這裡有一個小妙招就是將這個 DUMP 壓縮一下。由於 DUMP 檔案是記憶體轉儲檔案,大部分都是全零的內容,壓縮率非常高。如果需要透過網路等方式傳輸,那壓縮一下再傳輸會快很多

分析 DUMP 的工具有很多,我著重要和大家介紹的是太陽系最強 IDE —— VisualStudio。VisualStudio 已經是一個成熟的 IDE 了,只需將 DUMP 拖進去就可以了,聰明的 VisualStudio 可以自動幫咱進行分析

一般而言,將 DUMP 拖入到 Visual Studio 裡面,接著點選混合除錯按鈕即可。混合除錯是使用 託管 除錯和 本機 除錯的組合。託管除錯是指除錯 .NET 程式,本機除錯是指除錯其他非 .NET 系的程式。混合除錯是指同時除錯託管和本機程式碼,因為一般而言 .NET 系的應用要在託管層崩潰是有點難度的,除非開發者自己比較缺乏處理。然而本機程式碼,如某些使用 C 、彙編、C++ 編寫的程式,那就容易崩潰了。混合除錯可以同時除錯這兩種程式碼。即使程序完全不是 .NET 程式,也可以使用混合除錯來除錯

進入混合除錯之後,需要等待 Visual Studio 自動分析。如果是第一次除錯 DUMP 檔案的,可能會在下載符號這一步卡住一會。大家可以出去喝個茶,等待一下,再回來看看。實在等不急了,那就點選取消符號載入再繼續吧

好的,現在咱的進度就是在使用者側發現了問題,且不能透過事件檢視器等結束戰鬥。將使用者的 DUMP 檔案撈回來,透過 Visual Studio 進行分析。分析的方法就是將 DUMP 檔案拖入 Visual Studio 裡面,然後點選混合除錯按鈕。等待 Visual Studio 自動分析,即可看到分析結果

那聰明的 Visual Studio 會幫咱分析出什麼內容呢?如何看 Visual Studio 的分析結果呢?常見的套路就是關注 Visual Studio 以下三個方面內容

  • 呼叫堆疊
  • 後文會介紹的 "三板斧" 內容
  • 區域性變數

先來和大家介紹一下呼叫堆疊。呼叫堆疊是個好東西,呼叫堆疊是一個非常重要的內容,可以幫助我們瞭解到程式是如何執行的。透過呼叫堆疊可以看到程式是如何執行的,是從哪個函式開始的,是如何呼叫的,是如何返回的。預設的 Visual Studio 除錯佈局裡面,可以快速看到呼叫堆疊窗格

呼叫堆疊可以如何看?呼叫堆疊可以和著之前在使用者端工作管理員所見內容進行一起分析。如在工作管理員看不見程序,即對應程序崩了的問題,可以透過呼叫堆疊嘗試看到是誰帶崩的,崩之前呼叫的是哪個函式。如果是在工作管理員能看到程序,但是 CPU 使用率不動,那可能是死鎖問題,可以透過呼叫堆疊看到是哪個函式卡住了主執行緒或進入鎖。如果是 CPU 使用率爆高,那可能是死迴圈問題,可以透過呼叫堆疊看到是哪個函式跑滿了執行緒

舉個真實的例子,以下就是我從使用者端撈回來的一個 DUMP 檔案。透過 Visual Studio 分析,崩潰之前的呼叫堆疊如下

>	00000000()	Unknown
 	[Frames below may be incorrect and/or missing]	Unknown
 	nvumdshim.dll!710d0745()	Unknown
 	nvd3dum.dll!5989f2e1()	Unknown
 	nvd3dum.dll!595f1716()	Unknown
 	nvd3dum.dll!596b7827()	Unknown
 	nvd3dum.dll!598a6233()	Unknown
 	nvd3dum.dll!5989b95c()	Unknown
 	nvd3dum.dll!5989c33b()	Unknown
 	nvd3dum.dll!598816bc()	Unknown
 	nvumdshim.dll!710ca40e()	Unknown
 	nvumdshim.dll!710cbb78()	Unknown
 	nvumdshim.dll!710ca17f()	Unknown
 	nvumdshim.dll!710ca0d3()	Unknown
 	d3d9.dll!5ab86f81()	Unknown
 	ntdll.dll!_NtWaitForMultipleObjects@20 ()	Unknown
 	KERNELBASE.dll!76f69723()	Unknown

透過呼叫堆疊可以看到是 nvumdshim.dll 模組帶崩的。這個模組是 NVIDIA 顯示卡驅動的模組。透過這個呼叫堆疊可以看到是 NVIDIA 顯示卡驅動帶崩的。這個問題的解決方法就是更新 NVIDIA 顯示卡驅動。此問題詳細請看 記因為 NVIDIA 顯驅錯誤而讓 WPF 應用啟動閃退問題

驅動問題是客戶端崩的常見問題,表現就是在很多使用者電腦工作好好的,在某些使用者就起不來

修復 DirectX 時,我常用的就是 DirectX 修復工具,此工具下載地址是: https://blog.csdn.net/VBcom/article/details/6962388

講完了誰帶崩的問題,接下來再看另一個案例。對應 CPU 不動的問題,如下圖所示的呼叫堆疊

大家猜猜上面堆疊告訴咱什麼問題

透過以上的堆疊可以知道進入了鎖。此時的常見套路就是從上到下找找,找第一個咱自己程式集的呼叫函式,如這裡就找到了是在 lindexi.dll 裡面的方法。可以知道的是這個方法有邏輯在等待鎖,且這個鎖就不返回。此時配合程式碼食用更佳。咱這裡能夠知道程序卡住的原因是因為等待鎖,且這個鎖不返回,而至於這個鎖在業務上是什麼作用就需要咱進一步配合程式碼進行分析了

再來看看對應 CPU 爆高的一個案例,此時堆疊裡面的資訊可以告訴咱,現在正在跑的方法是哪些。有可能就是當前的呼叫堆疊的頂部的幾個方法有邏輯跑滿了執行緒了。同樣,此時配合程式碼食用更佳

但有可能此時面對的情況是沒有程式碼。如使用的是第三方庫等,此時靠堆疊資訊是不夠的。先讓大家思考這個問題,如果此時沒有程式碼還可以如何進一步分析?我將在後文和大家介紹如何透過三板斧來進一步分析

回顧一下,這就是咱拖入 DUMP 檔案之後,依靠 Visual Studio 裡面的呼叫堆疊進行問題分析的常見三個案例。對應軟體崩潰的問題,可以透過呼叫堆疊看到是誰帶崩的。對應 CPU 不動的問題,可以透過呼叫堆疊看到是誰卡住了主執行緒。對應 CPU 爆高的問題,可以透過呼叫堆疊看到是誰跑滿了執行緒

但是僅靠呼叫堆疊可能還是不夠的,有時候需要更多的資訊。接下來我將和大家介紹如何透過“三板斧”來進一步分析

這裡介紹的“三板斧”分別是暫存器、反彙編、記憶體這三個方面的工具。透過這三個方面的工具可以幫助我們進一步的分析問題

需要說明的是用到這三個工具時僅僅只是在咱有需要了解更多狀態資訊的時候。而且透過這三個工具也不一定能夠準確瞭解到問題的原因。這三個工具的使用本身不難,但是其難點確是這幾個工具所見內容的背後大家關於程式本身的理解以及軟體執行機制的瞭解。如果對於軟體執行機制不瞭解,那這三個工具所見內容可能會讓人難以理解,或者是調查方向跑偏

依然使用剛才的例子,當看到 CPU 爆高的時候,透過呼叫堆疊可以看到是哪個方法跑滿了執行緒。但是這個方法邏輯跑滿了,其原因是什麼呢?呼叫堆疊可無法回答此問題

試試先在 Visual Studio 裡面開啟記憶體、暫存器、反彙編窗格。這三個工具可以幫助我們進一步分析問題

開啟之後的 Visual Studio 的介面佈局大概如上圖所示

拿本課程的 CPU 爆高的例子,先透過反彙編發現了可能存在的問題,如想看看 rcx 暫存器裡面存放了什麼。透過暫存器窗格可以看到 rcx 暫存器裡面存放了什麼內容。透過記憶體窗格可以看到這個地址裡面存放了什麼內容。剛好就看到了對應的記憶體裡面存放了一段逗比程式碼

使用 “三板斧” 本身的難度不大,但是其難點在於其背後的知識。如彙編知識,暫存器的機制,以及軟體本身的執行機制。這部分知識遠遠超過了本課程能介紹的範圍,需要大家自行學習,但由於這部分知識的學習成本較高,所以在實際工作中,這部分知識可能並不是必須的。我只敢推薦大家在有餘力的情況下進行學習,如果平時工作已經很忙了學不過來了,那這部分知識還可以先放著。但是如果能夠掌握這部分知識,那在除錯問題時會有所幫助

繼續和大家介紹 Visual Studio 的另一個除錯工具——區域性變數。區域性變數也是個好東西,可以幫助我們瞭解到程式執行時的狀態。透過區域性變數可以看到程式執行時的變數的值,可以幫助我們瞭解到程式執行時的狀態

如看到了錯誤之前的區域性變數有一個名為 lastErrorCode 的變數,也許可以透過這個變數的值來了解到錯誤的原因。但是這個錯誤碼是什麼意思呢?這個錯誤碼的含義在哪裡找呢?咱可以試試 error 這個工具,這個工具可以自動幫助咱找到可能的錯誤碼的含義。這是工具是微軟整理的,絕大部分呼叫系統層的元件所見的錯誤碼都可以在這裡找到

工具下載地址: https://learn.microsoft.com/en-us/windows/win32/debug/system-error-code-lookup-tool

如在這裡咱可以看到的錯誤資訊是檔案或資料夾名錯誤,根據咱的業務邏輯,可能是檔名錯誤導致的問題。那接下來的調查方向就是看看為什麼出現錯誤的檔名了,這時候也許一看程式碼就理解了

再舉另一個真實的例子,如看到的是如上圖的異常導致的崩潰。根據咱透過搜尋引擎瞭解到的知識,這個 WindowsCodecs.dll 是 Windows 系統的 WIC 多媒體解碼層。可能此時遇到的問題和圖片等多媒體的編解碼有關

剛好在本例子裡面,透過區域性變數看到了出問題的圖片的檔案地址,此時的調查就更加有方向了。除了可能存在的 WIC 層的問題外,還可以是圖片檔案本身的問題。如圖片檔案投毒等問題

延伸一下,如何瞭解圖片、音影片等檔案是否被投毒了?這裡推薦一個工具,透過 MediaInfo 工具可以幫助咱看到檔案的許多資訊

如這個檔案就是一個假裝是 png 的 WebP 檔案,然後投毒將 WIC 層搞崩了

MediaInfo 工具下載地址: https://mediaarea.net/en/MediaInfo/Download

好像… 還是有些問題除錯不出來

太陽系最強 IDE 也頂不住呀

那就試試上接近能除錯一切的 WinDbg 吧

這個工具非常強大,只是有一個問題。那就是有億點點上手門檻

在這裡我告訴大家一個非常簡單的方法,讓大家瞬間就能學會上手使用 WinDbg 工具除錯問題。方法就是請一個熟悉 WinDbg 的夥伴,讓他幫你除錯,找到一個工具人幫你使用 WinDbg 除錯問題是最快能學會使用 WinDbg 的方法

回顧一下,以上咱就聊了在使用者端發現問題,先嚐試使用 Windows 自帶工具快速進行定位問題。以及撈到 DUMP 檔案之後,如何在開發機器上透過 Visual Studio 進行進一步分析。分析的方法就是將 DUMP 檔案拖入 Visual Studio 裡面,然後點選混合除錯按鈕。等待 Visual Studio 自動分析,即可看到分析結果。分析的重點是呼叫堆疊、三板斧、區域性變數。透過這三個方面的工具可以幫助我們進一步的分析問題

如果 Visual Studio 還不能解決問題,那就找個工具人來幫忙使用 WinDbg 繼續調查問題

這就是第一個大方向的內容

第二個大方向就是事後現場的復現問題。什麼時候需要復現問題?比如最簡單來說就是軟體啟動即崩潰,完全來不及開啟工作管理員撈 DUMP 檔案。這時候就需要復現問題了,透過復現問題可以幫助我們更好的定位問題

復現問題時也不是隻是簡單重複跑程式,而是可以透過更多的工具輔助來在復現問題時更好的定位問題

首要介紹的就是 ProcDump 工具

當使用工作管理員撈不到 DUMP 或不好撈 DUMP 時,使用 ProcDump 工具能夠更好的幫助我們撈 DUMP 檔案。ProcDump 工具是 Sysinternals 的工具,下載地址是: https://learn.microsoft.com/zh-cn/sysinternals/downloads/procdump

為什麼說有時候不好使用工作管理員撈 DUMP 呢?因為現實往往很複雜。除了閃崩,軟體啟動即崩潰導致的手速不夠快,撈不到 DUMP 檔案之外,還有其他很多問題。比如軟體就是處於似崩未崩的狀態,期望抓到某個時機的狀態,如軟體一定會在某次 CPU 爆高之後不能符合預期工作,然而 CPU 爆高的時間非常短,靠人類去看去抓是有些廢程式猿的。比如軟體半夜崩潰,只有在午夜12點才會崩潰,這時候人類可能已經睡著了,即使沒睡著,可能錯過了這個時間點就要等明天的午夜12點了。再比如是非必現的問題,需要壓測才能復現,期望自動化收集,否則可能要跑幾千次才能復現一次,靠人類的工作量有些大

透過 ProcDump 可以在程式萬種死法中有效的生成 Dump 檔案,只需使用好 ProcDump 的引數。具體引數作用可以參考 微軟官方文件如何在 NET 程式萬種死法中有效的生成 Dump (上) - 一線碼農 - 部落格園

這是一個小遊戲,讓大家連連線,看看在什麼情況下應該使用什麼方法

在調查思路這裡,復現問題時經常伴隨使用 ProcDump 工具,因為 ProcDump 工具可以在非常多的情況下幫助我們撈 DUMP 檔案

復現問題時,不僅只有 ProcDump 工具。還有可能面對的是事後現場的情況,此時需要使用更多的工具來輔助定位問題。以及當沒有調查思路時,可以試試常見的問題的探索幫助尋找思路

來和大家講講事後現場的調查

什麼是事後現場?事後現場問題在這裡一般說的是當前的現場或能復現所抓取到的現場已經不是問題發生的現場,而是發生問題之後的現場了

比如找到問題了,但問題非本質問題。常見的就是透過 DUMP 分析是如 空 異常的情況,導致崩潰的原因是因為空指標異常。但是空指標異常是如何產生的呢?這時候就需要透過事後現場分析思路調查來進一步分析問題

比如發生問題的地方不是產生問題的地方。如本課程的例子裡面,崩潰原因是一張假裝 png 的 WebP 圖片,那這張圖片是哪裡來的,為什麼會使用這張圖片。如果此時程式碼邏輯沒有幫助的話,那就需要進一步透過復現問題調查事前現場來進一步分析問題

比如系統性的問題。常見的就是團伙作案,不是單個應用導致的問題。這類問題的難度在於其複雜度,可能難以抓到正確的現場。此時也需要透過多次復現問題,抓取更多的資訊,透過事前和事後現場的分析來進一步分析問題

面對事後現場和團伙作案等問題,採用微軟極品工具箱的 Process Monitor 工具,配合 DebugView 工具通常都能有不錯的收穫

Process Monitor 工具下載地址: https://learn.microsoft.com/zh-cn/sysinternals/downloads/portmon

Debugview++ 工具開源地址: https://github.com/CobaltFusion/DebugViewPP

DebugView 工具下載地址: https://learn.microsoft.com/en-us/sysinternals/downloads/debugview

從介面和互動上,DebugView++ 比 DebugView 更好用一些

舉個真實栗子來和大家演示多個工具之間的配合使用來呼叫一個有趣且複雜的問題

這個問題的開始是測試同學和我報告了觸控失效問題,後來經過進一步調查發現其實是 explorer 未響應問題,表現就是 explorer 迷之閃黑

這個問題複雜之處在於 explorer 不是咱的,咱也不熟悉,也不知道是什麼導致的。而且 explorer 太龐大了,撈到 DUMP 分析壓力過大,耗時耗力。需要使用更多的工具輔助進一步分析問題

此時透過 Process Monitor 工具抓取 explorer 程序資訊,發現瞭如上圖的有趣的內容。裡面很受我關注的就是存在了程序退出

透過網上四處搜發現 explorer 是一個多程序軟體,程序的退出和迷之閃黑可能有所影響。既然程序退出了,那就試試上 ProcDump 工具在程序之前之後抓一個 DUMP 檔案回來分析

由於 explorer 十分龐大,且咱也不熟悉 explorer 的程式碼,來回抓了幾次 DUMP 分析都沒有什麼收穫。直到某次抓取到了一個有趣的 DUMP 檔案,透過這個 DUMP 檔案發現了在程序退出之前的呼叫堆疊裡面包含了 Shell32 的一些呼叫

再根據前面的 Process Monitor 工具抓到的在程序退出之前碰的是 Realtek Bluetooth 藍芽模組,於是重心就在 Shell32 和藍芽一起組合上面

既然大概定位到這裡,那就繼續上 ShellView 工具。透過 ShellView 工具進行大量的 Shell32 元件的禁用,我的做法大概就是看哪個不開森就禁用哪個,進行二分法的禁用,最終發現了是 Realtek Bluetooth 藍芽模組導致的問題

二分法的禁用就是先一口氣禁用一半的元件,看看問題是否解決。如果解決了,那就說明問題在這一半里面。如果沒有解決,那就說明問題在另一半里面。然後再在這一半里面繼續二分禁用,直到找到問題所在

經過以上的調查工具可以瞭解到是藍芽相關模組的問題,集中火力找到明確的除錯方向,很快就找到是藍芽驅動的問題

詳細的除錯內容可比這裡介紹的有趣的很,請看 記一次除錯資源管理器未響應經驗

相關文章