后台服务程序开发模式(一)
?
在2000/XP等基于NT 的操作系統(tǒng)中,有一個(gè)服務(wù)管理器,它管理的后臺進(jìn)程被稱為 service。
服務(wù)是一種應(yīng)用程序類型,它在后臺運(yùn)行,與 UNIX 后臺應(yīng)用程序類似。服務(wù)應(yīng)用程序通常可以
在本地和通過網(wǎng)絡(luò)為用戶提供一些功能,例如客戶端/服務(wù)器應(yīng)用程序、Web 服務(wù)器、數(shù)據(jù)庫服
務(wù)器以及其他基于服務(wù)器的應(yīng)用程序。
??? 后臺服務(wù) 程序是在后臺悄悄運(yùn)行的。我們通過將自己的程序登記為服務(wù),可以使自己的程序不出現(xiàn)
在任務(wù)管理器中,并且隨系統(tǒng)啟動而最先運(yùn)行,隨系統(tǒng)關(guān)閉而最后停止。
????
???? 服務(wù)控制管理器是一個(gè)RPC 服務(wù)器,它顯露了一組應(yīng)用編程接口,程序員可以方便的編寫程序來配置
服務(wù)和控制遠(yuǎn)程服務(wù)器中服務(wù)程序。
???? 服務(wù)程序通常編寫成控制臺類型的應(yīng)用程序,總的來說,一個(gè)遵守服務(wù)控制管理程序接口要求的程序
包含下面三個(gè)函數(shù):
1。服務(wù)程序主函數(shù)(main):調(diào)用系統(tǒng)函數(shù) StartServiceCtrlDispatcher 連接程序主線程到服務(wù)控制管理程序。
2。服務(wù)入口點(diǎn)函數(shù)(ServiceMain):執(zhí)行服務(wù)初始化任務(wù),同時(shí)執(zhí)行多個(gè)服務(wù)的服務(wù)進(jìn)程有多個(gè)服務(wù)入口函數(shù)。
3。控制服務(wù)處理程序函數(shù)(Handler):在服務(wù)程序收到控制請求時(shí)由控制分發(fā)線程引用。(此處是Service_Ctrl)。
?另外在系統(tǒng)運(yùn)行此服務(wù)之前需要安裝登記服務(wù)程序:installService 函數(shù)。刪除服務(wù)程序則需要先刪除服務(wù)安裝登記:removeService 函數(shù)。
?
服務(wù)類型:
| 類型 | 說明 |
| SERVICE_FILE_SYSTEM_DRIVER=2 | 文件系統(tǒng)驅(qū)動服務(wù)。 |
| SERVICE_KERNEL_DRIVER=1 | 驅(qū)動服務(wù)。 |
| SERVICE_WIN32_OWN_PROCESS=16 | 獨(dú)占一個(gè)進(jìn)程的服務(wù)。 |
| SERVICE_WIN32_SHARE_PROCESS=32 | 與其他服務(wù)共享一個(gè)進(jìn)程的服務(wù)。 |
新建WIN32控制臺程序, 其源文件名為service.cpp 。我用的開發(fā)工具是VC++.NET。
?
1.服務(wù)程序主函數(shù)
??? 服務(wù)控制管理程序啟動服務(wù)程序后,等待服務(wù)程序主函數(shù)調(diào)用系統(tǒng)函StartServiceCtrlDispatcher。一個(gè)SERVICE_WIN32_OWN_PROCESS 類型的服務(wù)應(yīng)該立即調(diào)用 StartServiceCtrlDispatcher 函數(shù),可以在服務(wù)啟動后讓服務(wù)入口點(diǎn)函數(shù)完成初始化工作。對于 SERVICE_WIN32_OWN_PROCESS 類型的服務(wù)和程序中所有服務(wù)共同的初始化工作可以在主函數(shù)中完成,但不要超過30秒。否則必須建立另外的線程完成這些共同的初始化工作,從而保證服務(wù)程序主函數(shù)能及時(shí)地調(diào)用 StartServiceCtrlDispatcher 函數(shù)。
?
?
主函數(shù)處理了三中命令行參數(shù):- install,- remove,- debug,分別用于安裝,刪除和調(diào)試服務(wù)程序。如果不帶參數(shù)運(yùn)行,則認(rèn)為是服務(wù)控制管理出現(xiàn)啟動該服務(wù)程序。參數(shù)不正確則給出提示信息。
?
StartServiceCtrlDispatcher 函數(shù)負(fù)責(zé)把程序主線程連接到服務(wù)控制管理程序。具體描述如下:
BOOL StartServiceCtrlDispatcher(
? const LPSERVICE_TABLE_ENTRY lpServiceTable);
lpServiceStartTable 指向 SERVICE_TABLE_ENTRY 結(jié)構(gòu)類型的數(shù)組,他包含了調(diào)用進(jìn)程所提供的每個(gè)服務(wù)的入口函數(shù)和字符串名。表中的最后一個(gè)元素必須為 NULL,指明入口表結(jié)束。SERVICE_TABLE_ENTRY 結(jié)構(gòu)具體描述如下:
?
typedef struct _SERVICE_TABLE_ENTRY {? LPTSTR lpServiceName;? LPSERVICE_MAIN_FUNCTION lpServiceProc;
} SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;
?
lpServiceName 是一個(gè)以 NULL 結(jié)尾的字符串,標(biāo)識服務(wù)名。如果是 SERVICE_WIN32_OWN_PROCESS 類型的服務(wù),這個(gè)字符串會被忽略。
lpServiceProc 指向服務(wù)入口點(diǎn)函數(shù)。
?
?
| //服務(wù)程序主函數(shù)。 #include "stdafx.h" #include "Windows.h" #define SZAPPNAME????? "serverSample"???? //服務(wù)程序名 #define SZSERVICENAME? "serviceSample"??? //標(biāo)識服務(wù)的內(nèi)部名 ? //內(nèi)部變量 bool?????????????????? bDebugServer=false; SERVICE_STATUS????????????? ssStatus; SERVICE_STATUS_HANDLE? sshStatusHandle; DWORD?????????????????????? dwErr=0; TCHAR?????????????????????? szErr[256]; ? //下面的函數(shù)由程序?qū)崿F(xiàn) void? WINAPI? Service_Main(DWORD dwArgc, LPTSTR *lpszArgv); void? WINAPI? Service_Ctrl(DWORD dwCtrlCode); void installService(); void removeService(); void debugService(int argc,char** argv); bool ReportStatusToSCMgr(DWORD dwCurrentState,DWORD dwWin32ExitCode,DWORD dwWaitHint); void AddToMessageLog(LPTSTR lpszMsg); ? int _tmain(int argc, _TCHAR* argv[]) {??? ???? SERVICE_TABLE_ENTRY dispatchTable[]= ???? { ???????? {TEXT(SZSERVICENAME),(LPSERVICE_MAIN_FUNCTION)Service_Main}, ???????? { NULL,NULL} ???? }; ???? if((argc>1)&&((*argv[1]=='-')||(argv[1]=="/"))) ???? { ???????? if(_stricmp("install",argv[1]+1)==0) ???????? { ????????????? installService(); ???????? } ???????? else if(_stricmp("remove",argv[1]+1)==0) ???????? { ????????????? removeService(); ???????? } ???????? else if(_stricmp("debug",argv[1]+1)==0) ???????? { ????????????? bDebugServer=true; ????????????? debugService(argc,argv); ???????? } ???????? else ???????? {??????? //如果未能和上面的如何參數(shù)匹配,則可能是服務(wù)控制管理程序來啟動該程序。立即調(diào)用 ?????????????????? //StartServiceCtrlDispatcher 函數(shù)。 ???????? ???? printf("%s - install to install the service \n",SZAPPNAME); ????????????? printf("%s - remove to remove the service \n",SZAPPNAME); ????????????? printf("%s - debug to debug the service \n",SZAPPNAME); ????????????? printf("\n StartServiceCtrlDispatcher being called.\n"); ????????????? printf("This may take several seconds.Please wait.\n"); ????????????? if(!StartServiceCtrlDispatcher(dispatchTable)) ?????????????????? AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed.")); ????????????? else ?????????????????? AddToMessageLog(TEXT("StartServiceCtrlDispatcher OK.")); ???????? } ???????? exit(0); ???? } ???? return 0; } |
轉(zhuǎn)載于:https://www.cnblogs.com/huqingyu/archive/2004/07/21/26246.html
總結(jié)
以上是生活随笔為你收集整理的后台服务程序开发模式(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 偶得
- 下一篇: 拿到两封信,开心ING