2007-01-27

[程式技巧] 腦殘 (簡易, 無痛) Windows NT (Win32) Service VC++ Debug (除錯) 方式

這次為了拜金勇者還有以後網路遊戲伺服器需要,需要寫一個 Windows NT Service (或者現在微軟改名叫做 Win32 Service)。

MSDN 裡面有個範例很不錯,執行起來也正常。

可惜的是,翻遍 MSDN 與網路搜尋,總是找不到滿意的 Debug (除錯) 方式。因為 Service 啟動與執行的過程中,不會開出任何視窗,甚至無法跳出任何 Dialog 顯示資訊 (用 MessageBox() 還會當機)。

所以,MSDN 提供的官方除錯方式,或是網路上討論的方法,不是太複雜需要弄東弄西,就是不知所云。還有看到很多人其實也為這所苦。要靠只是輸出除錯訊息,沒辦法設立中斷點,其實是很痛苦的事。

最後,從線上 MSDN 文件還有這個範例的 Source Code 裡面,發現有個方法,雖然很腦殘,但至少行得通。為避免自己忘記,也提供給正在苦惱的網友做個參考,所以趕快上來部落格公開分享。


  1. 首先,依照範例裡面的註解,想要除錯的時候,請把 StartService() 之前的 DebugBreak(); 該行取消註解(如果你拿到的範例沒有,請自行加上 DebugBreak() 的指令,MSDN 有指令詳細說明)。將 .exe 輸出改成 Debug (或 WinDebug) 模式,才可以包含所有 VC++ Debug 模式下的指令,並載入除錯符號表

    這時候,如果按 F5 開始執行,就會出現一個 Debug Dialog ,說是有中斷發生。若不想執行,直接按 F7 編譯成執行檔即可。

    然後,按照正常程序,把 Service 用 CreateService() 註冊。在範例裡面,是下 "-i" 的執行參數。



  2. 再來,開啟 Service Control Panel ,這個也有 VC++ 範例,網路上也有許多人寫類似的程式,在此就不贅述,下面這個則是我自己用 VB 寫的。

    如果剛剛 Service 有安裝好,正常的狀態應該是 Service Stopped。

    然後,啟動你自己寫的 Service 。這裡要注意,從啟動 Service 的指令下達開始,緊接著的步驟,需要在 15 ~ 30 秒內完成,否則 Windows 就會認為 Service 發生錯誤沒辦法啟動,會停止它。



  3. 重點來了。程式會出現下面的畫面,一開始我還以為是程式當掉!結果不是,這個畫面會出現,原因就是剛剛在 VC++ Source code 裡面,下達 DebugBreak(); 命令造成的。

    這時候請「火速」按下「除錯」按鈕



  4. 終於,看到 VC++ (MSDEV.exe) 被載進來,並且跳出一個 Dialog 告訴你,發生了中斷。

    先不管三七二十一,馬上再次「火速」按下 F5,趕在 15 ~ 30 秒內,讓你的 Service 程式繼續動起來。

    如果你發現程式繼續在運作 (Title Bar 有 [run] 字樣出現),沒有跳出 Service 被 Windows 強停的錯誤訊息畫面跳出來,就表示成功了!Windows 已經認為 Service 成功啟動,不會再繼續監視你的 Service ,就可以不用繼續那麼急驚風,進入自己的除錯程序。



  5. 這邊要開始進入普通的除錯程序。先在選單 Debug 項目選擇 Break 指令,把程式中斷。

    如果只看到一大堆 Assembly 的指令,也沒看到自己的程序在 Call Stack 視窗出現,不用緊張。再選擇選單的 Debug 項目,並按下 Threads 項目(在下面的圖片中是灰色 Disable 不能按,必須先用 Break 停下程式,才可以按它。)。



  6. 應該會出現類似下面的 Thread 選擇視窗,就可以點選正在執行你想看的程序的那條 Thread ,開始除錯這條 Thread (就跟一般 Multi-Thread 的除錯方式一樣)。



  7. 常用 VC++ 的人應該會知道,以非設立中斷點的方式,強制中斷以後,常常會進入 Disassembly Code 視窗。

    沒有關係,多按幾次 F10 或 F11,直到出現 Disassembly 跟你的 C++ Source 同時出現的畫面,就可以了。




  8. 最後,就看個人習慣。如果你並不關心 Source Code 被編譯成怎樣的 Assembly code,只要關閉 Disassembly Code 的視窗,就會回到如下面的圖片所示的一般正常 C++ Source Code 畫面,進入跟平常一樣的除錯程序。

    可以看下面的範例,除錯視窗內的訊息也可以看見了!




請記得,這個方法每次啟動,就會執行 MSDEV.exe ,而叫出一次 VC++ 的 IDE 介面。所以,除錯結束時,要記得關閉該次啟動的 VC++ ,否則就會一直跑出很多 VC++ 的執行畫面,搞不清楚哪一個才是正在除錯中的。

沒有留言:

將目前〔網頁 / 文章〕加入書籤: