在2000/XP等基於NT 的操作系統中,有一個服務管理器,它管理的後臺進程被稱爲 service。
服務是一種應用程序類型,它在後臺運行,與 Unix 後臺應用程序類似。服務應用程序通常可以
在本地和通過網絡爲用戶提供一些功能,例如客戶端/服務器應用程序、Web 服務器、數據庫服
務器以及其他基於服務器的應用程序。
後臺服務 程序是在後臺悄悄運行的。我們通過將自己的程序登記爲服務,可以使自己的程序不出現
在任務管理器中,並且隨系統啓動而最先運行,隨系統關閉而最後停止。
服務控制管理器是一個RPC 服務器,它顯露了一組應用編程接口,程序員可以方便的編寫程序來配置
服務和控制遠程服務器中服務程序。
服務程序通常編寫成控制檯類型的應用程序,總的來說,一個遵守服務控制管理程序接口要求的程序
包含下面三個函數:
1。服務程序主函數(main):調用系統函數 StartServiceCtrlDispatcher 連接程序主線程到服務控制管理程序。
2。服務入口點函數(ServiceMain):執行服務初始化任務,同時執行多個服務的服務進程有多個服務入口函數。
3。控制服務處理程序函數(Handler):在服務程序收到控制請求時由控制分發線程引用。(此處是Service_Ctrl)。
另外在系統運行此服務之前需要安裝登記服務程序:installService 函數。刪除服務程序則需要先刪除服務安裝登記:removeService 函數。
服務類型:
類型 |
說明 |
SERVICE_FILE_SYSTEM_DRIVER=2 |
文件系統驅動服務。 |
SERVICE_KERNEL_DRIVER=1 |
驅動服務。 |
SERVICE_WIN32_OWN_PROCESS=16 |
獨佔一個進程的服務。 |
SERVICE_WIN32_SHARE_PROCESS=32 |
與其他服務共享一個進程的服務。 |
新建WIN32控制檯程序, 其源文件名爲service.cpp 。我用的開發工具是VC++.NET。
1.服務程序主函數
服務控制管理程序啓動服務程序後,等待服務程序主函數調用系統函StartServiceCtrlDispatcher。一個SERVICE_WIN32_OWN_PROCESS 類型的服務應該立即調用 StartServiceCtrlDispatcher 函數,可以在服務啓動後讓服務入口點函數完成初始化工作。對於 SERVICE_WIN32_OWN_PROCESS 類型的服務和程序中所有服務共同的初始化工作可以在主函數中完成,但不要超過30秒。否則必須建立另外的線程完成這些共同的初始化工作,從而保證服務程序主函數能及時地調用 StartServiceCtrlDispatcher 函數。
主函數處理了三中命令行參數:- install,- remove,- debug,分別用於安裝,刪除和調試服務程序。如果不帶參數運行,則認爲是服務控制管理出現啓動該服務程序。參數不正確則給出提示信息。
StartServiceCtrlDispatcher 函數負責把程序主線程連接到服務控制管理程序。具體描述如下:
BOOL StartServiceCtrlDispatcher(
const LPSERVICE_TABLE_ENTRY lpServiceTable);
lpServiceStartTable 指向 SERVICE_TABLE_ENTRY 結構類型的數組,他包含了調用進程所提供的每個服務的入口函數和字符串名。表中的最後一個元素必須爲 NULL,指明入口表結束。SERVICE_TABLE_ENTRY 結構具體描述如下:
typedef struct _SERVICE_TABLE_ENTRY { LPTSTR lpServiceName; LPSERVICE_MAIN_FUNCTION lpServiceProc;
} SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;
lpServiceName 是一個以 NULL 結尾的字符串,標識服務名。如果是 SERVICE_WIN32_OWN_PROCESS 類型的服務,這個字符串會被忽略。
lpServiceProc 指向服務入口點函數。
//服務程序主函數。 #include "stdafx.h" #include "Windows.h" #define SZAPPNAME "serverSample" //服務程序名 #define SZSERVICENAME "serviceSample" //標識服務的內部名
//內部變量 bool bDebugServer=false; SERVICE_STATUS ssStatus; SERVICE_STATUS_HANDLE sshStatusHandle; DWORD dwErr=0; TCHAR szErr[256];
//下面的函數由程序實現 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 { //如果未能和上面的如何參數匹配,則可能是服務控制管理程序來啓動該程序。立即調用 //StartServiceCtrlDispatcher 函數。 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; } |
上一篇: C++學習筆記-後臺服務程序開發模式(三)
下一篇: C++學習筆記-後臺服務程序開發模式(二)