一個建立NT服務的類

作者:Joerg Koenig

翻譯:Yuan Wenmao

原文:A Class For Building An NT Service

曾經嘗試寫一個NT服務嗎?

我最近的一個項目需要開發一個CORBA服務,將其運行成NT服務,由於下一個項目也是需要NT服務,我就想花點時間把他做得通用一點給更多的項目使用。成果就是這個CNTService類,通過CodeGurus與大家分享。

通過這個類可以很容易的創建NT服務,所有的困難部分都被這個類完成了,你只需派生出你自己的類並重寫”Run()”和”Stop()”兩純虛函數就可以了。當然還有好幾個虛函數可以重寫。

         這個類接受一組命令行參數。比如說你可以使用-d選項使其按控制檯程序運行,這樣調試起來就容易多了。

此外這個類還可以安裝卸載服務,也是通過命令行參數控制(當然你也可以重定義它)。
 CNTService支持UNICODE和非UNICODE兩種編譯方式。

建立一個服務

現在讓我們親眼看看如何創建一個自己的服務。

步驟如下(假設你使用的是VC++5.0)

1.       創建一個新的控制檯應用程序工程文件。

2.       把NTService文件包放入新工程文件目錄中。

3.       將 "NTService.cpp" 和"NTServiceEventLogMsg.mc" 添加到工程中。

4.       打開 Project->Settings ... 對話框並且如下圖所示填寫。

5.       編譯"NTServiceEventLogMsg.mc"文件. 這樣會產生 "NTServiceEventLogMsg.h" 和"NTServiceEventLogMsg.rc"兩個文件。

6.       將產生的資源文件添加到工程中。

7.       從CNTService類派生出自己的服務類並且重寫至少兩個方法"Run()"和"Stop()"。

8.       寫一個簡單的"main()" 函數去啓動你程序的功能(你可以使用 sample 工程作爲一個好的起點)。

9.       一旦工程編譯沒有錯誤了,你就可以立即啓動它。這之前你應該打再次打開 Project->Settings ... 對話框,選擇 AllConfigurations ,選中工程名字那一行,激活 Debug 標籤並在Program arguments:域增加 -d 選項。

現在你可以將你的服務當控制檯程序運行並調試了,可以使用Ctrl-C或Ctrl-Break去停止服務(這會模擬一個對SCM(Service Control Manager)的停止請求)。


如何填寫文件NTServiceEventLogMsg.mc的配置

現在讓我們將服務開啓爲一個真正的NT服務(假定使用Sample工程)

1.       如果你的賬號不屬於管理員組,切換爲管理員賬戶登入(這會是有些事情容易點)。

2.       使用 –i選項開啓程序. 這樣就安裝了你的服務。

3.       如果最後一步順利完成, 你就可以打開控制面板啓動 Services程序。查找你的服務的顯示名字並選中它(如果你嘗試的是sample程序,則顯示名字叫Very Simple Service )。

4.       按下 Startup ... 按鈕,查看 LogOn As:項,現在可以勾選System Account。如果是sample程序,確保你勾選了 Interact With The Desktop項。這是必需的,因爲sample程序使用了MessageBox()函數(這與桌面有關)。如果不勾選此項,sample 不僅不能正確運行還會自動掛起;如此你將不能再次停止服務!只要稍有經驗便可增強sample程序,使它在安裝此服務的同時便選中此選項,但我想保證sample 程序儘可能的簡單,所以這個問題留給你實現。

Sample工程實現了一個非常簡單的服務。派生類(聲明和實現)和main()函數都包含在同一個文件當中(main.cpp)。這個文件少於100行(去除註釋可以確保一頁紙就能打印!)

服務只是每10秒彈出一個消息框。

更多信息,參看 CNTService.h- sample工程。我相信這是很好的註釋(如果有意見,告知我)。

改變的修訂版

·        命令行參數中增加兩個切換選項: -e 使運行中的服務停止(類中的相應方法爲:virtual BOOL EndService())和-s 如果服務未運行,使服務開啓(對應方法:virtual BOOL StartupService())。

·        Todd C. Wilson 增加了對Win95的支持。這使得你可以創建一個像Windows 95程序的服務(所謂的"Faceless Application",無界面應用程序)。就想服務一樣, 這樣的應用程序會跟隨系統自動啓動且一個用戶註銷後仍然存在。 我的經歷對此類應用程序作用不大:我可以註銷, 在我再次登入前系統是掛起的。 而且 BoundsChecker 5 (是的,我經常使用這個強大的工具測試我的程序)說, 下列語句返回一個無效指針(準確的說應該是“返回的指針未指向一個函數”)

 typedef DWORD (WINAPI *fp_RegServProc)(DWORDdwProcessId,DWORD dwType); 
 fp_RegServProc fncptr=NULL; 
// ... 
HMODULE hModule =::GetModuleHandle(TEXT("kernel32.dll")); 
fncptr=(fp_RegServProc)::GetProcAddress(hModule,"RegisterServiceProcess"); 
if (fncptr!=NULL) 
    (*fncptr)(0, RSP_SIMPLE_SERVICE); 

如果達到最後一句,BoundsChecker 警告說, 指針fncptr 未指向一個函數。然而,sample繼續執行未碰到嚴重的錯誤。

如果你打算開發一個windows95下的無界面應用程序,就需要注意這個問題。 Sample工程提供了配置項"Win32 Win95 Debug",你可以用來嘗試此新特性。

NTService 使用 MFC

微軟推薦將NT服務寫成控制檯應用程序。但是,也有可能將使用MFC寫NT服務。 如此,並不需要創建一個MFC嚮導程序(當然也可以這樣做,不過需要移除一些代碼,因爲通常你不需要文檔&視圖結構),一個簡單的Win32程序就夠了。確保你選擇了工程中Settings對話框General標籤中的Using MFC in a shared DLL項。此外,你還需選擇C/C++標籤中的Multithreaded DLL / DebugMultithreaded DLLCode Generation 域的 Use run-time Library
如果你使用了預編譯頭文件,確保不要定義 #define VC_EXTRALEAN,因爲基於MFC的服務需要partsof the "rarely used stuff",這個宏會拒絕windows頭文件 。

我增加了一個MFC示例新工程MFCService 作爲sample服務工作區的一部分。嘗試將它作爲一個更復雜服務的起點。服務(安裝、刪除等)操作和上一章所講一樣。

CNTService包含三個文件: 
NTService.h 
NTService.cpp 
NTServiceEventLogMsg.mc 
Download Source 14KB 
Download Sample Project 23KB

注意:NTServiceEventLogMsg.mc 文件爲Telic Software International B.V.版權所有。

感謝Telic提供

最後更新時間: February 5, 1999

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章