




版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度技術(shù)合作項(xiàng)目終止及解除合同書
- 2025年度農(nóng)村水井承包合同與農(nóng)業(yè)灌溉用水權(quán)流轉(zhuǎn)及監(jiān)管協(xié)議
- 2025年度特殊年齡段勞動(dòng)者用工協(xié)議及權(quán)益保障
- 2025年度個(gè)體商戶勞動(dòng)合同(家政服務(wù)行業(yè)合作)
- 5G通信借款居間合同模板
- 2025年度分紅股收益確認(rèn)與分配協(xié)議
- 2025年度影視作品著作權(quán)許可及廣告植入合作合同
- 2025年度分手協(xié)議書模板:分手后共同債務(wù)承擔(dān)協(xié)議
- 2025年度房屋拆除與建筑垃圾清運(yùn)一體化服務(wù)合同
- 2025年度企業(yè)導(dǎo)師帶徒技能傳承服務(wù)協(xié)議
- (中職)電子技術(shù)基礎(chǔ)與技能(電子信息類)教案
- 汪小蘭有機(jī)化學(xué)課件(第四版)3
- 減少電力監(jiān)控系統(tǒng)告警信息上傳方法的研究(QC成果)
- 如何發(fā)揮好辦公室協(xié)調(diào)、督導(dǎo)、服務(wù)職能
- 交易商協(xié)會(huì)非金融企業(yè)債務(wù)融資工具發(fā)行注冊(cè)工作介紹
- 《人與環(huán)境》課程教學(xué)大綱
- 班組長管理能力提升培訓(xùn)(PPT96張)課件
- 深圳市城市用地分類表
- 內(nèi)蒙古自治區(qū)小額貸款公司試點(diǎn)管理實(shí)施細(xì)則
- 勞務(wù)分包入住生活區(qū)承諾書
- 直系親屬關(guān)系證明(存根)(共1頁)
評(píng)論
0/150
提交評(píng)論