后臺(tái)服務(wù)程序開發(fā)_第1頁
后臺(tái)服務(wù)程序開發(fā)_第2頁
后臺(tái)服務(wù)程序開發(fā)_第3頁
后臺(tái)服務(wù)程序開發(fā)_第4頁
后臺(tái)服務(wù)程序開發(fā)_第5頁
已閱讀5頁,還剩6頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、一直感覺VC+太復(fù)雜了,但昨天看了汪蒲陽編著的因特網(wǎng)應(yīng)用編程,其中寫到后臺(tái)服務(wù)程序的編寫,論述的非常詳細(xì),而且邏輯清晰,看了之后感覺明白不少,故拿來與需要之人共享,并更正了原程序的一些錯(cuò)誤,補(bǔ)充了一些材料。另外還有一種用C+編寫后臺(tái)服務(wù)程序的思路(不算.NET上服務(wù)程序開發(fā)模型),以后整理好了再發(fā)上來。在2000/XP等基于NT 的操作系統(tǒng)中,有一個(gè)服務(wù)管理器,它管理的后臺(tái)進(jìn)程被稱為 service。服務(wù)是一種應(yīng)用程序類型,它在后臺(tái)運(yùn)行,與 UNIX 后臺(tái)應(yīng)用程序類似。服務(wù)應(yīng)用程序通常可以在本地和通過網(wǎng)絡(luò)為用戶提供一些功能,例如客戶端/服務(wù)器應(yīng)用程序、Web 服務(wù)器、數(shù)據(jù)庫服務(wù)器以及其他基于服

2、務(wù)器的應(yīng)用程序。后臺(tái)服務(wù) 程序是在后臺(tái)悄悄運(yùn)行的。我們通過將自己的程序登記為服務(wù),可以使自己的程序不出現(xiàn)在任務(wù)管理器中,并且隨系統(tǒng)啟動(dòng)而最先運(yùn)行,隨系統(tǒng)關(guān)閉而最后停止。服務(wù)控制管理器是一個(gè)RPC 服務(wù)器,它顯露了一組應(yīng)用編程接口,程序員可以方便的編寫程序來配置服務(wù)和控制遠(yuǎn)程服務(wù)器中服務(wù)程序。服務(wù)程序通常編寫成控制臺(tái)類型的應(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ù),同

3、時(shí)執(zhí)行多個(gè)服務(wù)的服務(wù)進(jìn)程有多個(gè)服務(wù)入口函數(shù)。3??刂品?wù)處理程序函數(shù)(Handler):在服務(wù)程序收到控制請(qǐng)求時(shí)由控制分發(fā)線程引用。(此處是Service_Ctrl)。 另外在系統(tǒng)運(yùn)行此服務(wù)之前需要安裝登記服務(wù)程序:installService 函數(shù)。刪除服務(wù)程序則需要先刪除服務(wù)安裝登記:removeService 函數(shù)。服務(wù)類型:類型說明SERVICE_FILE_SYSTEM_DRIVER2文件系統(tǒng)驅(qū)動(dòng)服務(wù)。SERVICE_KERNEL_DRIVER1驅(qū)動(dòng)服務(wù)。SERVICE_WIN32_OWN_PROCESS16獨(dú)占一個(gè)進(jìn)程的服務(wù)。SERVICE_WIN32_SHARE_PROCESS32

4、與其他服務(wù)共享一個(gè)進(jìn)程的服務(wù)。新建WIN32控制臺(tái)程序, 其源文件名為service.cpp 。我用的開發(fā)工具是VC+.NET。1服務(wù)程序主函數(shù)服務(wù)控制管理程序啟動(dòng)服務(wù)程序后,等待服務(wù)程序主函數(shù)調(diào)用系統(tǒng)函StartServiceCtrlDispatcher。一個(gè)SERVICE_WIN32_OWN_PROCESS 類型的服務(wù)應(yīng)該立即調(diào)用 StartServiceCtrlDispatcher 函數(shù),可以在服務(wù)啟動(dòng)后讓服務(wù)入口點(diǎn)函數(shù)完成初始化工作。對(duì)于 SERVICE_WIN32_OWN_PROCESS 類型的服務(wù)和程序中所有服務(wù)共同的初始化工作可以在主函數(shù)中完成,但不要超過30秒。否則必須建立另外

5、的線程完成這些共同的初始化工作,從而保證服務(wù)程序主函數(shù)能及時(shí)地調(diào)用 StartServiceCtrlDispatcher 函數(shù)。主函數(shù)處理了三中命令行參數(shù):- install,- remove,- debug,分別用于安裝,刪除和調(diào)試服務(wù)程序。如果不帶參數(shù)運(yùn)行,則認(rèn)為是服務(wù)控制管理出現(xiàn)啟動(dòng)該服務(wù)程序。參數(shù)不正確則給出提示信息。StartServiceCtrlDispatcher 函數(shù)負(fù)責(zé)把程序主線程連接到服務(wù)控制管理程序。具體描述如下:BOOL StartServiceCtrlDispatcher(const LPSERVICE_TABLE_ENTRY lpServiceTable);lpSe

6、rviceStartTable 指向 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_ENTRYLPTSTR lpServiceName; LPSERVICE_MAIN_FUNCTION lpServiceProc; SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;lpServiceName 是一個(gè)以 NULL 結(jié)尾的字符串,

7、標(biāo)識(shí)服務(wù)名。如果是 SERVICE_WIN32_OWN_PROCESS 類型的服務(wù),這個(gè)字符串會(huì)被忽略。lpServiceProc 指向服務(wù)入口點(diǎn)函數(shù)。/服務(wù)程序主函數(shù)。#include "stdafx.h"#include "Windows.h"#define SZAPPNAME"serverSample"/服務(wù)程序名#define SZSERVICENAME"serviceSample"/標(biāo)識(shí)服務(wù)的內(nèi)部名/內(nèi)部變量boolbDebugServer=false;SERVICE_STATUSssStatus;SER

8、VICE_STATUS_HANDLEsshStatusHandle;DWORDdwErr=0;TCHARszErr256;/下面的函數(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,

9、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)&&(*argv1='-')|(argv1="/")if(_stricmp("ins

10、tall",argv1+1)=0)installService();else if(_stricmp("remove",argv1+1)=0)removeService();else if(_stricmp("debug",argv1+1)=0)bDebugServer=true;debugService(argc,argv);else/如果未能和上面的如何參數(shù)匹配,則可能是服務(wù)控制管理程序來啟動(dòng)該程序。立即調(diào)用/StartServiceCtrlDispatcher 函數(shù)。printf("%s - install to install

11、 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(!StartS

12、erviceCtrlDispatcher(dispatchTable)AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed.");elseAddToMessageLog(TEXT("StartServiceCtrlDispatcher OK.");exit(0);return 0;2服務(wù)入口點(diǎn)函數(shù)服務(wù)入口點(diǎn)函數(shù) service_main 首先調(diào)用系統(tǒng)函數(shù) RegisterServiceCtrlHandler 注冊(cè)服務(wù)控制處理函數(shù) service_ctrl,然后調(diào)用 ReportStatusToSC

13、Mgr 函數(shù),它通過系統(tǒng)函數(shù) SetServiceStatus 更新服務(wù)的狀態(tài),然后調(diào)用特定的服務(wù)初始化入口函數(shù) ServiceStart 完成具體的初始化工作。/服務(wù)入口點(diǎn)函數(shù)void ServiceStart(DWORD dwArgc,LPTSTR* lpszArgv);/具體服務(wù)的初始化入口函數(shù) void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)/注冊(cè)服務(wù)控制處理函數(shù)sshStatusHandle=RegisterServiceCtrlHandler(TEXT(SZSERVICENAME),Service_Ctrl)

14、;/如果注冊(cè)失敗if(!sshStatusHandle)goto cleanup;return;/初始化 SERVICE_STATUS 結(jié)構(gòu)中的成員ssStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;ssStatus.dwServiceSpecificExitCode=0;/更新服務(wù)狀態(tài)if(!ReportStatusToSCMgr(SERVICE_START_PENDING,/服務(wù)狀態(tài),The service is starting.NO_ERROR, /退出碼3000) /等待時(shí)間goto cleanup; /更新服務(wù)狀態(tài)失敗則轉(zhuǎn)向 clean

15、upServiceStart(dwArgc,lpszArgv);return;cleanup:/把服務(wù)狀態(tài)更新為 SERVICE_STOPPED,并退出。if(sshStatusHandle)(void)ReportStatusToSCMgr(SERVICE_STOPPED,dwErr,0);3控制處理程序函數(shù)函數(shù) Service_Ctrl 是服務(wù)的控制處理程序函數(shù),由主函數(shù)線程的控制分發(fā)程序引用。在處理控制請(qǐng)求碼時(shí),應(yīng)該在確定的時(shí)間間隔內(nèi)更新服務(wù)狀態(tài)檢查點(diǎn),避免發(fā)生服務(wù)不能響應(yīng)的錯(cuò)誤。/控制處理程序函數(shù)void WINAPI Service_Ctrl(DWORD dwCtrlCode)/處理

16、控制請(qǐng)求碼switch(dwCtrlCode)/先更新服務(wù)狀態(tài)為 SERVICDE_STOP_PENDING,再停止服務(wù)。case SERVICE_CONTROL_STOP:ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);ServiceStop();/由具體的服務(wù)程序?qū)崿F(xiàn)return;/暫停服務(wù)case SERVICE_CONTROL_PAUSE:ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);ServicePause();/由具體的服務(wù)程序?qū)崿F(xiàn)ssStatus.dwCu

17、rrentState=SERVICE_PAUSED;return;/繼續(xù)服務(wù)case SERVICE_CONTROL_CONTINUE:ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);ServiceContinue();/由具體的服務(wù)程序?qū)崿F(xiàn)ssStatus.dwCurrentState=SERVICE_RUNNING;return;/更新服務(wù)狀態(tài)case SERVICE_CONTROL_INTERROGATE:break;/無效控制碼default:break;ReportStatusToSCMgr(ssStatus.dwCurr

18、entState,NO_ERROR,0);除了系統(tǒng)定義的五種控制碼外(還有一種是:SERVICE_CONTROL_SHUTDOWN),用戶還可自定義控制碼,其取值范圍是128-255。用戶可以通過控制面板中的服務(wù)項(xiàng)向特定服務(wù)程序的控制處理函數(shù)發(fā)送控制碼,程序員可以調(diào)用系統(tǒng)函數(shù) ControlService 直接向服務(wù)程序的控制處理函數(shù)發(fā)送控制碼。其函數(shù)原型如下:BOOL ControlService(SC_HANDLE hService,DWORD dwControl,LPSERVICE_STATUS lpServiceStatus);hService :函數(shù) OpenService or C

19、reateService 返回的服務(wù)程序句柄。dwControl :控制碼,不能是SERVICE_CONTROL_SHUTDOWN。lpServiceStatus:返回最后收到的服務(wù)狀態(tài)信息。4安裝服務(wù)程序每個(gè)已安裝服務(wù)程序在 HKEY_LOCAL_MACHINESYSTECurrentControlSetServices 下都有一個(gè)服務(wù)名的關(guān)鍵字,程序員可以調(diào)用系統(tǒng)函數(shù) CreateService 安裝服務(wù)程序,并指定服務(wù)類型,服務(wù)名等。這個(gè)函數(shù)創(chuàng)建一個(gè)服務(wù)對(duì)象,并將其增加到相關(guān)的服務(wù)控制管理器數(shù)據(jù)庫中。下面是函數(shù)原型: SC_HANDLE CreateService( SC_HA

20、NDLE hSCManager, /服務(wù)控制管理程序維護(hù)的登記數(shù)據(jù)庫的句柄,由系統(tǒng)函數(shù)OpenSCManager 返回 LPCTSTR lpServiceName, /以NULL 結(jié)尾的服務(wù)名,用于創(chuàng)建登記數(shù)據(jù)庫中的關(guān)鍵字 LPCTSTR lpDisplayName, /以NULL 結(jié)尾的服務(wù)名,用于用戶界面標(biāo)識(shí)服務(wù) DWORD dwDesiredAccess, /指定服務(wù)返回類型 DWORD dwServiceType, /指定服務(wù)類型 DWORD dwStartType, /指定何時(shí)啟動(dòng)服務(wù) DWORD dwErrorControl, /指定服務(wù)啟動(dòng)失敗的嚴(yán)重程度 LPCTSTR lpBi

21、naryPathName, /指定服務(wù)程序二進(jìn)制文件的路徑 LPCTSTR lpLoadOrderGroup, /指定順序裝入的服務(wù)組名 LPDWORD lpdwTagId, /忽略,NULL LPCTSTR lpDependencies, /指定啟動(dòng)該服務(wù)前必須先啟動(dòng)的服務(wù)或服務(wù)組 LPCTSTR lpServiceStartName, /以NULL 結(jié)尾的字符串,指定服務(wù)帳號(hào)。如是NULL,則表示使用LocalSystem 帳號(hào) LPCTSTR lpPassword /以NULL 結(jié)尾的字符串,指定對(duì)應(yīng)的口令。為NULL表示無口令。但使用LocalSystem時(shí)填NULL);對(duì)于一個(gè)已安裝

22、的服務(wù)程序,可以調(diào)用系統(tǒng)函數(shù) OpenService 來獲取服務(wù)程序的句柄下面是其函數(shù)原型:SC_HANDLE OpenService( SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD dwDesiredAccess);hSCManager :服務(wù)控制管理程序微服的登記數(shù)據(jù)庫的句柄。由函數(shù) OpenSCManager function 返回 這個(gè)句柄。 lpServiceName :將要打開的以NULL 結(jié)尾的服務(wù)程序的名字,和 CreateService 中的 lpServiceName 相對(duì)應(yīng)。 dwDesiredAccess :指定服

23、務(wù)的訪問類型。服務(wù)響應(yīng)請(qǐng)求時(shí),首先檢查訪問類型。用CreateService 或OpenService 打開的服務(wù)程序句柄使用完畢后必須用CloseServiceHandle 關(guān)閉。OpenSCManager打開的服務(wù)管理數(shù)據(jù)庫句柄也必須用它來關(guān)閉。/安裝服務(wù)程序void installService()SC_HANDLE schService;SC_HANDLE schSCManager;TCHAR szPath512;/得到程序磁盤文件的路徑if(GetModuleFileName(NULL,szPath,512)=0)_tprintf(TEXT("Unable to insta

24、ll %s - %s n"),TEXT(SZAPPNAME),GetLastError();/1獲取調(diào)用函數(shù)返回的最后錯(cuò)誤碼return;/打開服務(wù)管理數(shù)據(jù)庫schSCManager=OpenSCManager(NULL,/本地計(jì)算機(jī)NULL,/默認(rèn)的數(shù)據(jù)庫SC_MANAGER_ALL_ACCESS/要求所有的訪問權(quán));if(schSCManager)/登記服務(wù)程序schService=CreateService(schSCManager,/服務(wù)管理數(shù)據(jù)庫句柄TEXT(SZSERVICENAME),/服務(wù)名TEXT(SZAPPNAME),/用于顯示服務(wù)的標(biāo)識(shí)SERVICE_ALL_A

25、CCESS,/響應(yīng)所有的訪問請(qǐng)求SERVICE_WIN32_OWN_PROCESS,/服務(wù)類型SERVICE_DEMAND_START,/啟動(dòng)類型SERVICE_ERROR_NORMAL,/錯(cuò)誤控制類型szPath,/服務(wù)程序磁盤文件的路徑NULL,/服務(wù)不屬于任何組NULL,/沒有tag標(biāo)識(shí)符NULL,/啟動(dòng)服務(wù)所依賴的服務(wù)或服務(wù)組,這里僅僅是一個(gè)空字符串NULL,/LocalSystem 帳號(hào)NULL);if(schService)_tprintf(TEXT("%s installed. n"),TEXT(SZAPPNAME);CloseServiceHandle(sc

26、hService);else_tprintf(TEXT("CreateService failed - %s n"),GetLastError();CloseServiceHandle(schSCManager);else_tprintf(TEXT("OpenSCManager failed - %s n"),GetLastError();5停止和刪除已安裝的服務(wù)程序 /停止和刪除已安裝的服務(wù)程序void removeService()SC_HANDLEschService;SC_HANDLEschSCManager;/打開服務(wù)管理數(shù)據(jù)庫sch

27、SCManager=OpenSCManager(NULL,/本地計(jì)算機(jī)NULL,/默認(rèn)的數(shù)據(jù)庫SC_MANAGER_ALL_ACCESS/要求所有的訪問權(quán));if(schSCManager)/獲取服務(wù)程序句柄schService=OpenService(schSCManager,/服務(wù)管理數(shù)據(jù)庫句柄TEXT(SZSERVICENAME),/服務(wù)名SERVICE_ALL_ACCESS/響應(yīng)所有的訪問請(qǐng)求);if(schService)/試圖停止服務(wù)if(ControlService(schService,/服務(wù)程序句柄SERVICE_CONTROL_STOP,/停止服務(wù)請(qǐng)求碼&ssSta

28、tus/接收最后的服務(wù)狀態(tài)信息)_tprintf(TEXT("Stopping %s."),TEXT(SZAPPNAME);Sleep(1000);/等待服務(wù)停止/while(QueryServiceStatus(schService,&ssStatus)if(SERVICE_STOP_PENDING=ssStatus.dwCurrentState)_tprintf(TEXT(".");Sleep(1000);elsebreak;if(SERVICE_STOPPED=ssStatus.dwCurrentState)_tprintf(TEXT(&q

29、uot;n %s stopped. n"),TEXT(SZAPPNAME);else_tprintf(TEXT("n %s failed to stopp. n"),TEXT(SZAPPNAME);/刪除已安裝的服務(wù)程序安裝if(DeleteService(schService)_tprintf(TEXT("%s removed. n"),TEXT(SZAPPNAME);else_tprintf(TEXT("DeleteService failed - %s. n"), GetLastError();CloseService

30、Handle(schService);else_tprintf(TEXT("OpenService failed - %s n"),GetLastError();CloseServiceHandle(schSCManager);else_tprintf(TEXT("OpenSCManager failed - %s n"),GetLastError();在編譯程序的時(shí)候,我們會(huì)發(fā)覺ServiceStop();ServicePause();ServiceContinue();等三個(gè)函數(shù)沒有具體實(shí)現(xiàn),這對(duì)于理解此文的人來說應(yīng)該不難編寫,在此我可以給點(diǎn)文檔內(nèi)的

31、參考:聲明     SetTheServiceStatus()函數(shù),/        /  SetTheServiceStatus -   This just wraps up SetServiceStatus.   /    void SetTheServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,     &#

32、160;                      DWORD dwCheckPoint,   DWORD dwWaitHint)         SERVICE_STATUS ss;  / Current status of the service.   &

33、#160;  /       / Disable control requests until the service is started.      /       if (dwCurrentState = SERVICE_START_PENDING)         ss.dwControlsAccepted = 0;   

34、;   else         ss.dwControlsAccepted =                       SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;     

35、60;                 / Other flags include SERVICE_ACCEPT_PAUSE_CONTINUE                       / and SERVICE_ACCEPT_SHUTDOWN.      / Initialize ss structure. 

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論