1、关于Windows服务的编程方法关于Windows服务的编程方法windows服务有两种,一种是驱动服务程序,另外一种是win32服务程序,我们这里只谈win32服务程序,查看win32服务程序,可以这样:开始运行services.msc可以打开windows自带的服务程序控制程序。这个大家都应该很熟悉了吧。下面来讲讲利用vc编程来对win32服务程序进行管理,包括创建、删除已经对win32服务程序的运行状态进行管理。在进入编程之前先要理解几样东西:第一:服务控制管理器 service control manager(SCM),SCM在系统启动的时候就会启动,其主要的作用有以下几个方面:1)维
2、持了一张已安装的服务的数据表 2)根据策略在系统启动时启动服务或者在需要的时候启动服务 4)枚举已经安装的服务4)维持了正在运行的服务的状态信息 5)向正在运行的服务发送控制信息6)对服务数据库的锁定管理SCM所维持的数据库可以在注册表中找到:HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesSCM通过三类程序的方法来实现对服务的管理:Service program、Service configuration program 和 Service control program Service Program: 也就是被注册成服务的程序主体,他必须
3、符合服务控制器(SCM)的接口规范,这样才能被SCM控制(包括启动,停止等等),一个服务程序内可以包含一个服务或多个服务的执行代码,但是它们都拥有固定的三个部分:服务main函数,服务ServiceMain函数和服务Control Handler函数。 服务main函数:入口点函数,由于服务程序通常是以控制台的方式存在的,所以它们的入口点自然就是main函数。在服务控制管理器开始一个服务程序时,会等待StartServiceCtrlDispatcher函数的执行。如果服务类型是SERVICE_WIN32_OWN_PROCESS就会立即调用StartServiceCtrlDispatcher函数
4、的执行;如果服务类型是SERVICE_WIN32_SHARE_PROCESS,通常在初始化所有服务之后再调用它。StartServiceCtrlDispatcher这个函数的作用就是把服务入口点函数和SCM连接起来。服务ServiceMain函数:函数ServiceMain是服务的入口点。在服务控制程序请求一个新的服务启动时,服务控制管理器启动一个服务,并发送一个开始请求到控制调度程序,而后控制调度程序创建一个新线程来执行ServiceMain函数。ServiceMain须执行以下的任务:调用RegisterServiceCtrlHandler函数注册一个HandlerEx函数来向服务发送控制
5、请求信息,返回值是服务状态句柄用来向服务控制管理器传送服务状态。初始化后调用SetServiceStatus函数设置服务状态为SERVICE_RUNNING。最后,就是执行服务所要完成的任务。服务Control Handler函数:每个服务都有一个控制句柄HandlerEx函数。它会在服务进程从服务控制程序接收到一个控制请求时被控制调度程序所调用。无论何时在HandlerEx函数被调用时,都要调用SetServiceStatus函数向服务控制管理器报告它当前的状态。在用户关闭系统时,所有的控制句柄都会调用带有SERVICE_ACCEPT_SHUTDOW控制代码的SetServiceStatus
6、函数来接收NSERVICE_CONTROL_SHUTDOWN控制代码。这里是一个 Service program的例子:实现的功能就是打开一个端口一直监听,连接上来之后,发送一串数据,然后关闭连接。#include Afxwin.h#include windows.h#include stdio.h#include winsock2.h#pragma comment(lib,ws2_32)HANDLE hMutex;SERVICE_STATUS ServiceStatus;SERVICE_STATUS_HANDLE ServiceStatusHandle;/Service Control Ha
7、ndler Function void WINAPI CmdControl(DWORD dwCode) switch(dwCode) case SERVICE_CONTROL_PAUSE: ServiceStatus.dwCurrentState = SERVICE_PAUSED; break; case SERVICE_CONTROL_CONTINUE: ServiceStatus.dwCurrentState = SERVICE_RUNNING; break; case SERVICE_CONTROL_STOP: WaitForSingleObject(hMutex,INFINITE);
8、ServiceStatus.dwCurrentState = SERVICE_STOPPED; ServiceStatus.dwWin32ExitCode = 0; ServiceStatus.dwCheckPoint = 0; ServiceStatus.dwWaitHint = 0; if(SetServiceStatus(ServiceStatusHandle,&ServiceStatus)=0) printf(SetServiceStatus in CmdControl in Switch Error !n); return ; case SERVICE_CONTROL_INTERRO
9、GATE: break; default: break; if(SetServiceStatus(ServiceStatusHandle,&ServiceStatus)=0) printf(SetServiceStatus in CmdControl out Switch Error !n); return ;listenPort() WSADATA wsa; SOCKET sServer; SOCKET sClient; struct sockaddr_in sin; WSAStartup(MAKEWORD(2,2),&wsa); sServer = socket(AF_INET,SOCK_
10、STREAM,IPPROTO_TCP); if(sServer=INVALID_SOCKET) printf(Socket Error !n); return -1; sin.sin_family = AF_INET; sin.sin_port = htons(20540); sin.sin_addr.S_un.S_addr = INADDR_ANY; if(bind(sServer,(const struct sockaddr *)&sin,sizeof(sin)=SOCKET_ERROR) printf(Bind Error !n); return -1; if(listen(sServe
11、r,5)=SOCKET_ERROR) printf(Listen Error !n); return -1; hMutex=CreateMutex(NULL,FALSE,NULL); if(hMutex=NULL) printf(Create Mutex Error !n); while(1) sClient=accept(sServer,NULL,NULL); send(sClient,aa,sizeof(aa),0); closesocket(sClient); Sleep(1000); WSACleanup();/Service ServiceMain Function void WIN
12、API CmdStart(DWORD dwArgc,LPTSTR *lpArgv) ServiceStatus.dwServiceType = SERVICE_WIN32; ServiceStatus.dwCurrentState = SERVICE_START_PENDING; ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; ServiceStatus.dwServiceSpecificExitCode = 0; ServiceStatus.dwWin32ExitC
13、ode = 0; ServiceStatus.dwCheckPoint = 0; ServiceStatus.dwWaitHint = 0; ServiceStatusHandle=RegisterServiceCtrlHandler(ntkrnl,CmdControl); /注册控制响应程序 if(ServiceStatusHandle=0) printf(RegisterServiceCtrlHandler Error !n); return ; ServiceStatus.dwCurrentState = SERVICE_RUNNING; ServiceStatus.dwCheckPoi
14、nt = 0; ServiceStatus.dwWaitHint = 0; if(SetServiceStatus(ServiceStatusHandle,&ServiceStatus)=0) printf(SetServiceStatus in CmdStart Error !n); return ; listenPort(); return ;int main() SERVICE_TABLE_ENTRY DispatchTable = ntkrnl,CmdStart, NULL ,NULL ; StartServiceCtrlDispatcher(DispatchTable); /注意:C
15、mdStart函数 return 0;Service Configuration Programs:其作用有两个方面,第一是创建、删除和枚举服务,第二是用来更改或者查询已经安装的服务的信息。完成这些任务可以直接操作注册表,但是最好还是使用SCM 配置函数。SCM 配置函数需要一个SCManger对象或者一个service对象,要获得这些对象可以使用OpenSCManager函数,或者使用OpenService、CreateService获得service对象。 这里顺便就把Service Control Programs说了,其实也就是包含一些函数可以控制服务的启动,停止,相应的函数可以在ms
16、dn查询。下面是一个创建服务的例子,首先使用OpenSCMagenager获得一个SCManger对象,然后使用CreateService创建一个服务。#include windows.h#include stdio.h#include Winsvc.h#include TCHAR.h#pragma comment(lib,Advapi32.lib)int main() SC_HANDLE schManager; SC_HANDLE schService; DWORD dwBytesNeeded; LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL; L
17、PSERVICE_DESCRIPTION lpServiceDescription = NULL; SERVICE_STATUS ServiceStatus; DWORD dwIndex; schManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);/SC_MANAGER_ALL_ACCESS); if(schManager = NULL) printf(OpenschManager Error: %dn,GetLastError(); return FALSE; SC_HANDLE hdlServ = CreateService(
18、schManager, _T(test), _T(test), SC_MANAGER_ALL_ACCESS, 0x00000010, 3, /SERVICE_ALL_ACCESS, /SERVICE_WIN32_OWN_PROCESS, /SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, _T(d:test.exe), /这个就是由上面那个程序生成的exe文件 NULL,NULL,NULL,NULL,NULL ); if (hdlServ = NULL) DWORD gg = GetLastError(); printf(error!n); hdlServ
19、 = OpenService(schManager,_T(test),SC_MANAGER_ALL_ACCESS);/SERVICE_ALL_ACCESS); if (hdlServ = NULL) printf(OpenSerivce errorn); /* if (!DeleteService(hdlServ) printf(delete errorn); */ /查看服务状态 SERVICE_STATUS ss; if(QueryServiceStatus(hdlServ, &ss) = FALSE) printf(Error Service Status! %dn, GetLastEr
20、ror(); return FALSE; /如果服务已经启动,则退出 if(ss.dwCurrentState = SERVICE_RUNNING) return TRUE; /启动服务 StartService(hdlServ, 0, NULL); Sleep(1000); /查看服务状态 if(QueryServiceStatus(hdlServ, &ss) = FALSE) printf(Error Service Status! %dn, GetLastError(); return FALSE; if(ss.dwCurrentState != SERVICE_RUNNING) pri
21、ntf(Error in Starting Service! %dn, GetLastError(); CloseHandle(hdlServ); return FALSE; printf(nendn); return 0;最后,再举一个例子。ServiceAll()枚举所有的服务,并打印出来ServiceInformation(char *szServiceName)查询特定服务的具体信息#include windows.h#include stdio.h#include Winsvc.h#include TCHAR.h#pragma comment(lib,Advapi32.lib)BOO
22、L ServiceAll() SC_HANDLE schManager; DWORD dwServiceType; DWORD dwServiceState; DWORD dwIndex; DWORD cbBufSize; DWORD ResumeHandle; DWORD cbBytesNeeded; DWORD ServicesReturned; ENUM_SERVICE_STATUS EnumStatus512; schManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if(schManager = NULL) print
23、f(OpenschManager Error: %dn,GetLastError(); return FALSE; dwServiceType = SERVICE_WIN32; dwServiceState = SERVICE_STATE_ALL; cbBufSize = sizeof(EnumStatus); cbBytesNeeded = 0; ServicesReturned = 0; ResumeHandle = 0; if(!EnumServicesStatus(schManager,dwServiceType,dwServiceState, EnumStatus,cbBufSize
24、,&cbBytesNeeded, &ServicesReturned,&ResumeHandle) cbBufSize += cbBytesNeeded; if(!EnumServicesStatus(schManager,dwServiceType,dwServiceState, EnumStatus,cbBufSize,&cbBytesNeeded, &ServicesReturned,&ResumeHandle) printf(EnumServicesStatus Error: %dn,GetLastError(); return FALSE; else printf(Services:
25、t %dn,ServicesReturned); printf(tt= Services =nn); printf(%-20st%-10s%snn,ServiceName,Status,DisplayName); for(dwIndex = 0;dwIndex ServicesReturned; dwIndex +) printf(%-20st,EnumStatusdwIndex.lpServiceName); switch(EnumStatusdwIndex.ServiceStatus.dwCurrentState) case SERVICE_STOPPED: printf(%-10s,St
26、opped); break; case SERVICE_START_PENDING: printf(%-10s,Starting); break; case SERVICE_STOP_PENDING: printf(%-10s,Stopping); break; case SERVICE_RUNNING: printf(%-10s,Running); break; case SERVICE_CONTINUE_PENDING: printf(%-10s,Continue); break; case SERVICE_PAUSE_PENDING: printf(%-10s,Pausing); bre
27、ak; case SERVICE_PAUSED: printf(%-10s,Paused); break; default: printf(%-10s,); break; printf(%sn,EnumStatusdwIndex.lpDisplayName); printf(nTotal:t %dn,ServicesReturned); if(schManager != NULL) CloseServiceHandle(schManager); return TRUE;BOOL ServiceInformation(char *szServiceName) SC_HANDLE schManag
28、er; SC_HANDLE schService; DWORD dwBytesNeeded; LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL; LPSERVICE_DESCRIPTION lpServiceDescription = NULL; SERVICE_STATUS ServiceStatus; DWORD dwIndex; schManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); if(schManager = NULL) printf(OpenschManager Error
29、: %dn,GetLastError(); return FALSE; schService = OpenService(schManager,szServiceName,SERVICE_ALL_ACCESS); if(schService = NULL) if(GetLastError() = ERROR_INVALID_NAME) printf(%s no Found !n,szServiceName); return TRUE; printf(OpenService Error: %dn,GetLastError(); return FALSE; lpServiceConfig = (LPQUERY_SERVICE_CONFIG)malloc(1024*8); printf(tt= Configuration =nn); if(!QueryServiceConfig(schService,lpServiceConfig,1024*8,&dwBytesNeeded) printf(Qu
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1