《《WIN系统服务编程》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《WIN系统服务编程》PPT课件.ppt(79页珍藏版)》请在金锄头文库上搜索。
1、For: 分类信息 From: 新闻WindowsWindows系统编程实用教程系统编程实用教程系统编程实用教程系统编程实用教程授课教师:授课教师:职务:职务:For: 分类信息 From: 新闻第第9章章 Windows服务编程服务编程课程描述课程描述WindowsWindowsWindowsWindows服务是长服务是长服务是长服务是长期在后台运行、不期在后台运行、不期在后台运行、不期在后台运行、不与用户进行交互的与用户进行交互的与用户进行交互的与用户进行交互的程序。在程序。在程序。在程序。在C/SC/SC/SC/S结构结构结构结构的应用程序中通常的应用程序中通常的应用程序中通常的
2、应用程序中通常可以服务的形式开可以服务的形式开可以服务的形式开可以服务的形式开发服务器程序。有发服务器程序。有发服务器程序。有发服务器程序。有的应用程序中还需的应用程序中还需的应用程序中还需的应用程序中还需要检测和控制服务要检测和控制服务要检测和控制服务要检测和控制服务的状态。本章将介的状态。本章将介的状态。本章将介的状态。本章将介绍绍绍绍WindowsWindowsWindowsWindows服务编服务编服务编服务编程的基本方法。程的基本方法。程的基本方法。程的基本方法。For: 分类信息 From: 新闻本章知识点本章知识点9.1 Windows9.1 Windows服务的概念和管理服
3、务的概念和管理9.2 Windows9.2 Windows服务编程服务编程9.3 9.3 开发开发WindowsWindows服务程序服务程序9.4 9.4 增加和使用组件增加和使用组件For: 分类信息 From: 新闻9.1 Windows服务的概念和管理服务的概念和管理9.1.1 9.1.1 管理管理WindowsWindows服务服务9.1.2 9.1.2 服务控制器服务控制器For: 分类信息 From: 新闻9.1.1 管理管理Windows服务服务For: 分类信息 From: 新闻服务的属性对话框服务的属性对话框 For: 分类信息 From: 新闻命令行工具命
4、令行工具sc.exesc command service name .sc command service name .参数说明如下:参数说明如下:p,指定要连接的计算机,格式为,指定要连接的计算机,格式为“ ”。pcommandcommand,指定对服务进行的操作,具体如下:,指定对服务进行的操作,具体如下:query,查询服务的状态或枚举服务类型的状态。queryex,查询服务的扩展状态或枚举服务类型的状态。start,启动服务。pause,向服务发送 PAUSE 控制请求。interrogat,-向服务发送 INTERROGATE 控制请求。continue,向服务发送 CONTINUE
5、 控制请求。stop,向服务发送 STOP 请求。config,永久更改服务的配置。description,更改服务的描述。failure,更改服务失败时所进行的操作sidtype,更改服务的服务 SID 类型。qc,查询服务的配置信息。qdescription,查询服务的描述。For: 分类信息 From: 新闻接上接上qfailure,查询服务失败时所进行的操作qsidtype,查询服务的服务 SID 类型。delete,从注册表中删除服务。create, 创建服务(将其添加到注册表)control,向服务发送控制。sdshow,显示服务的安全描述符。sdset,设置服务的安全描述符。
6、showsid,显示与任意名称相对应的服务 SID。GetDisplayName,获取服务的显示名称。GetKeyName,获取服务的键名。EnumDepend,枚举服务的依存关系。pservice nameservice name,指定要操作的服务名。,指定要操作的服务名。For: 分类信息 From: 新闻【例【例9.1】p使用使用scsc命令查询服务命令查询服务MySQLMySQL的状态,命令如下:的状态,命令如下:sc query MySQLsc query MySQLFor: 分类信息 From: 新闻【例【例9.2】p使用使用scsc命令停止服务命令停止服务MySQLMyS
7、QL的状态,命令如下:的状态,命令如下:sc sc stopstop MySQL MySQLFor: 分类信息 From: 新闻9.1.2 服务控制器服务控制器p服务控制器(服务控制器(Service Control Manager Service Control Manager ,SCMSCM)是)是Windows NTWindows NT家族操作系统中的一个系统进程,它可以家族操作系统中的一个系统进程,它可以启动、停止启动、停止WindowsWindows服务,并与服务,并与WindowsWindows服务交流。服务交流。p服务控制器对应的可执行文件是服务控制器对应的可执行文件是%Sy
8、stemRoot%services.exe%SystemRoot%services.exe,它以,它以WindowsWindows控制台程控制台程序的形式运行。序的形式运行。For: 分类信息 From: 新闻注册表中关于服务的内容注册表中关于服务的内容For: 分类信息 From: 新闻注册表中服务包含的键值注册表中服务包含的键值名称说明DisplayName服务的显示名称。如果没有指定,则使用键名作为服务的名称Group指定服务所属得为服务组。如果没有指定,则该服务不属于任何服务组ErrorControl指定服务或设备驱动程序在加载和初始化时出现错误的处理方法。取值如下:0(忽略)
9、,忽略出现的错误,继续启动,不产生警告;1(正常),缺省值,继续启动,弹出一个警告消息框,并在系统日志中记录警告信息;2(严重),系统声明启动失败;3(紧急),系统声明启动失败,并停止启动过程,运行调试程序;ImagePath驱动程序或服务对应的可执行文件的位置ObjectName用于指定驱动程序对象的名称,用于加载驱动程序Start指定服务的启动方式。取值如下:0,由系统内核加载;1,由I/O管理器加载;2,由SCM加载;3,由用户手动启动Type指定服务的类型。For: 分类信息 From: 新闻9.2 Windows服务编程服务编程9.2.1 9.2.1 与与SCMSCM建立连接建立
10、连接9.2.2 9.2.2 创建服务创建服务9.2.3 9.2.3 打开服务打开服务9.2.4 9.2.4 枚举服务列表枚举服务列表9.2.5 9.2.5 启动服务启动服务9.2.6 9.2.6 停止服务停止服务9.2.7 9.2.7 查询服务的状态查询服务的状态9.2.8 9.2.8 修改修改服务的服务的配置参数配置参数For: 分类信息 From: 新闻9.2.1 与与SCM建立连接建立连接SC_HANDLE WINAPI OpenSCManager(SC_HANDLE WINAPI OpenSCManager( _in LPCTSTR lpMachineName, _in LPCTS
11、TR lpMachineName,/ / 指定要连接的目标计算机,指定要连接的目标计算机,如果为如果为NULLNULL或空字符串,则连接到本地计算机或空字符串,则连接到本地计算机 _in LPCTSTR lpDatabaseName, _in LPCTSTR lpDatabaseName, / / 要连接的服务控制器名字,要连接的服务控制器名字,应使用应使用SERVICES_ACTIVE_DATABASESERVICES_ACTIVE_DATABASE。如果使用。如果使用NULLNULL,则表示连接的默认,则表示连接的默认服务控制器服务控制器 _in DWORD dwDesiredAccess
12、 _in DWORD dwDesiredAccess/ / 指定对服务控制器的访问指定对服务控制器的访问权限权限););For: 分类信息 From: 新闻9.2.2 创建服务创建服务SC_HANDLE WINAPI CreateService(SC_HANDLE WINAPI CreateService( _in SC_HANDLE hSCManager, _in SC_HANDLE hSCManager, _in LPCTSTR lpServiceName, _in LPCTSTR lpServiceName, _in LPCTSTR lpDisplayName, _in LPCTST
13、R lpDisplayName, _in DWORD dwDesiredAccess, _in DWORD dwDesiredAccess, _in DWORD dwServiceType, _in DWORD dwServiceType, _in DWORD dwStartType, _in DWORD dwStartType, _in DWORD dwErrorControl, _in DWORD dwErrorControl, _in LPCTSTR lpBinaryPathName, _in LPCTSTR lpBinaryPathName, _in LPCTSTR lpLoadOrd
14、erGroup, _in LPCTSTR lpLoadOrderGroup, _out LPDWORD lpdwTagId, _out LPDWORD lpdwTagId, _in LPCTSTR lpDependencies, _in LPCTSTR lpDependencies, _in LPCTSTR lpServiceStartName, _in LPCTSTR lpServiceStartName, _in LPCTSTR lpPassword _in LPCTSTR lpPassword););For: 分类信息 From: 新闻【例【例9.3】p编写程序,将其自身安装为编写程
15、序,将其自身安装为WindowsWindows服务。自定义函数服务。自定义函数SvcInstall()SvcInstall()用于安装服务,代码如用于安装服务,代码如下:下:#include stdafx.h#include stdafx.h#include #include #include #include #define SVCNAME TEXT(SvcName)#define SVCNAME TEXT(SvcName)VOID SvcInstall()VOID SvcInstall() SC_HANDLE schSCManager; SC_HANDLE schSCManager; SC
16、_HANDLE schService; SC_HANDLE schService; TCHAR szPathMAX_PATH; TCHAR szPathMAX_PATH;/ / 获取当前程序的可执行文件的路径获取当前程序的可执行文件的路径 if( !GetModuleFileName( NULL, szPath, MAX_PATH ) ) if( !GetModuleFileName( NULL, szPath, MAX_PATH ) ) printf(Cannot install service (%d)n, GetLastError(); printf(Cannot install ser
17、vice (%d)n, GetLastError(); return; return; For: 分类信息 From: 新闻接上接上 / / 获取服务控制器数据库句柄获取服务控制器数据库句柄 schSCManager = OpenSCManager( schSCManager = OpenSCManager( NULL, / NULL, / 本地计算机本地计算机 NULL, / NULL, / 使用缺省的数据库使用缺省的数据库 SC_MANAGER_ALL_ACCESS); / SC_MANAGER_ALL_ACCESS); / 使用全部访问权限使用全部访问权限 if (NULL = sc
18、hSCManager) if (NULL = schSCManager) printf(OpenSCManager failed (%d)n, GetLastError(); printf(OpenSCManager failed (%d)n, GetLastError(); return; return; / / 安装服务安装服务 schService = CreateService( schService = CreateService( schSCManager, / schSCManager, / 服务控制器数据库句柄服务控制器数据库句柄 SVCNAME, / SVCNAME, / 服
19、务名服务名 SVCNAME, / SVCNAME, / 服务显示名服务显示名 For: 分类信息 From: 新闻接上接上SERVICE_ALL_ACCESS, / SERVICE_ALL_ACCESS, / 使用全部访问权限使用全部访问权限 SERVICE_WIN32_OWN_PROCESS, / SERVICE_WIN32_OWN_PROCESS, / 服务类型为在其自己的进程中运行的服务服务类型为在其自己的进程中运行的服务 SERVICE_DEMAND_START, / SERVICE_DEMAND_START, / 启动类型启动类型 SERVICE_ERROR_NORMAL, /
20、SERVICE_ERROR_NORMAL, / 错误控制类型错误控制类型 szPath, / szPath, / 服务可执行文件的路径服务可执行文件的路径 NULL, / NULL, / 没有加载顺序组没有加载顺序组 NULL, / NULL, / 没有标记标识符没有标记标识符 NULL, / NULL, / 没有依赖关系没有依赖关系 NULL, / NULL, / 使用使用LocalSystemLocalSystem账户运行服务账户运行服务 NULL); / NULL); / 不需要指定密码不需要指定密码 if (schService = NULL) if (schService = NUL
21、L) printf(CreateService failed (%d)n, GetLastError(); printf(CreateService failed (%d)n, GetLastError(); CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager); return; return; else printf(Service installed successfullyn); else printf(Service installed successfullyn); /关闭句柄关闭句柄 CloseServ
22、iceHandle(schService); CloseServiceHandle(schService); CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager); For: 分类信息 From: 新闻主函数主函数_tmain()int _tmain(int argc, _TCHAR* argv)int _tmain(int argc, _TCHAR* argv) / / 如果带有一个命令行参数如果带有一个命令行参数-install-install,则安装服务,则安装服务if(argc= 2 & ! strcm
23、p(argv1, -install)if(argc= 2 & ! strcmp(argv1, -install)SvcInstall();SvcInstall();/ / 下面是服务的代码下面是服务的代码return 0;return 0; 如果带有一个命令行参数如果带有一个命令行参数-install-install,则调用,则调用SvcInstall()SvcInstall()函数安函数安装服务。下面的代码可以设计服务的具体功能,本例中省略了装服务。下面的代码可以设计服务的具体功能,本例中省略了服务的具体功能。服务的具体功能。For: 分类信息 From: 新闻9.2.3 打开服务打开服
24、务SC_HANDLE WINAPI OpenService(SC_HANDLE WINAPI OpenService( _in SC_HANDLE hSCManager, _in SC_HANDLE hSCManager,/ / 调调用用OpenSCManager()OpenSCManager()函数返回的服务控制器句柄函数返回的服务控制器句柄 _in LPCTSTR lpServiceName, / _in LPCTSTR lpServiceName, / 要要打开的服务名打开的服务名 _in DWORD dwDesiredAccess _in DWORD dwDesiredAccess/
25、/ 对服务的访问权限对服务的访问权限););For: 分类信息 From: 新闻CloseServiceHandle()函数函数p对服务执行完操作之后,需要调用对服务执行完操作之后,需要调用CloseServiceHandleCloseServiceHandle()()函数关闭打开的服务句柄,函数原型如下:函数关闭打开的服务句柄,函数原型如下:BOOL WINAPI CloseServiceHandle(BOOL WINAPI CloseServiceHandle( _in SC_HANDLE hSCObject _in SC_HANDLE hSCObject/ / 要要关闭的服务句柄关闭
26、的服务句柄););For: 分类信息 From: 新闻9.2.4 枚举服务列表枚举服务列表BOOL WINAPI EnumServicesStatusEx(BOOL WINAPI EnumServicesStatusEx( _in SC_HANDLE hSCManager, _in SC_HANDLE hSCManager, _in SC_ENUM_TYPE InfoLevel, _in SC_ENUM_TYPE InfoLevel, _in DWORD dwServiceType, _in DWORD dwServiceType, _in DWORD dwServiceState, _i
27、n DWORD dwServiceState, _out LPBYTE lpServices, _out LPBYTE lpServices, _in DWORD cbBufSize, _in DWORD cbBufSize, _out LPDWORD pcbBytesNeeded, _out LPDWORD pcbBytesNeeded, _out LPDWORD lpServicesReturned, _out LPDWORD lpServicesReturned, _in_out LPDWORD lpResumeHandle, _in_out LPDWORD lpResumeHandle
28、, _in LPCTSTR pszGroupName _in LPCTSTR pszGroupName););For: 分类信息 From: 新闻【例【例9.4】编写程序,枚举并打印系统服务编写程序,枚举并打印系统服务。代码见书。代码见书。For: 分类信息 From: 新闻9.2.5 启动服务启动服务BOOL WINAPI StartService(BOOL WINAPI StartService( _in SC_HANDLE hService, _in SC_HANDLE hService,/ / 要要启动的服务的句柄启动的服务的句柄 _in DWORD dwNumServiceA
29、rgs, _in DWORD dwNumServiceArgs,/ / 指指定定lpServiceArgVectorslpServiceArgVectors数组中的字符串的数量数组中的字符串的数量 _in LPCTSTR* lpServiceArgVectors _in LPCTSTR* lpServiceArgVectors/ / 启动服务时的参数数组启动服务时的参数数组););p如果函数执行成功,则函数返回如果函数执行成功,则函数返回TRUETRUE;否则返回;否则返回FALSEFALSE。For: 分类信息 From: 新闻【例【例9.5】p编写程序,启动服务编写程序,启动服务Web
30、ClientWebClient,代码如下:,代码如下:#include stdafx.h#include stdafx.h#include #include #include #include int _tmain(int argc, _TCHAR* argv)int _tmain(int argc, _TCHAR* argv) SC_HANDLE hSC; / SC_HANDLE hSC; / 服务管理器句柄服务管理器句柄SC_HANDLE handle;SC_HANDLE handle;/服务句柄服务句柄hSC = :OpenSCManager( NULL, /*SERVICES_ACTI
31、VE_DATABASE*/NULL, hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, SC_MANAGER_ALL_ACCESS);SC_MANAGER_ALL_ACCESS);if(hSC = NULL)if(hSC = NULL) printf( printf( 无法连接服务管理器!无法连接服务管理器!););return 1;return 1; handle = :OpenService( hSC, WebClient, SERVICE_ALL_ACCESS);handle = :OpenService( hSC
32、, WebClient, SERVICE_ALL_ACCESS); For: 分类信息 From: 新闻接上接上if(handle = NULL)if(handle = NULL) printf( printf( 无法打开服务!无法打开服务!););return 1;return 1; if( :StartService( handle, NULL, NULL) = FALSE)if( :StartService( handle, NULL, NULL) = FALSE) printf( printf( 无法启动服务!无法启动服务!););return 2;return 2; return
33、 0;return 0; For: 分类信息 From: 新闻9.2.6 停止服务停止服务p调用调用ControlService ()ControlService ()函数可以停止指函数可以停止指定的服务,函数原型如下:定的服务,函数原型如下:BOOL WINAPI ControlService(BOOL WINAPI ControlService( _in SC_HANDLE hService, _in SC_HANDLE hService, / / 要停止的服务的要停止的服务的句柄句柄 _in DWORD dwControl, _in DWORD dwControl,/ / 制定一个控
34、制代制定一个控制代码码 _out LPSERVICE_STATUS lpServiceStatus / _out LPSERVICE_STATUS lpServiceStatus / 指向一个指向一个SERVICE_STATUSSERVICE_STATUS结构体,结构体, 用于接收服务状态用于接收服务状态););For: 分类信息 From: 新闻【例【例9.6】p编写程序,停止服务编写程序,停止服务WebClientWebClient,代码如下:,代码如下:#include stdafx.h#include stdafx.h#include #include #include #incl
35、ude int _tmain(int argc, _TCHAR* argv)int _tmain(int argc, _TCHAR* argv) SC_HANDLE hSC; / SC_HANDLE hSC; / 服务管理器句柄服务管理器句柄SC_HANDLE handle;SC_HANDLE handle;/服务句柄服务句柄hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, SC_MANAGER_A
36、LL_ACCESS);SC_MANAGER_ALL_ACCESS);if(hSC = NULL)if(hSC = NULL) printf( printf( 无法连接服务管理器!无法连接服务管理器!););return 1;return 1; handle = :OpenService( hSC, WebClient, SERVICE_ALL_ACCESS);handle = :OpenService( hSC, WebClient, SERVICE_ALL_ACCESS);For: 分类信息 From: 新闻接上接上if(handle = NULL)if(handle = NULL) p
37、rintf( printf( 无法打开服务!无法打开服务!););return 2;return 2; SERVICE_STATUS status;SERVICE_STATUS status;if( :ControlService( handle, SERVICE_CONTROL_STOP, if( :ControlService( handle, SERVICE_CONTROL_STOP, &status) = FALSE)&status) = FALSE) printf( printf( 无法停止服务!无法停止服务!););return 3;return 3; return 0;retur
38、n 0; For: 分类信息 From: 新闻9.2.7 查询服务的状态查询服务的状态p调用调用QueryServiceStatusEx ()QueryServiceStatusEx ()函数可以查询指定服务的状态,函数可以查询指定服务的状态,函数原型如下:函数原型如下:BOOL WINAPI QueryServiceStatus(BOOL WINAPI QueryServiceStatus( _in SC_HANDLE hService, _in SC_HANDLE hService, / / 服务的句柄服务的句柄 _out LPSERVICE_STATUS lpServiceStatu
39、s/ _out LPSERVICE_STATUS lpServiceStatus/ 使用使用SERVICE_STATUSSERVICE_STATUS结构体,用于接收服务的状态结构体,用于接收服务的状态););For: 分类信息 From: 新闻SERVICE_STATUS结构体结构体typedef struct _SERVICE_STATUS typedef struct _SERVICE_STATUS DWORD dwServiceType; DWORD dwServiceType; DWORD dwCurrentState; DWORD dwCurrentState; DWORD dw
40、ControlsAccepted; DWORD dwControlsAccepted; DWORD dwWin32ExitCode; DWORD dwWin32ExitCode; DWORD dwServiceSpecificExitCode; DWORD dwServiceSpecificExitCode; DWORD dwCheckPoint; DWORD dwCheckPoint; DWORD dwWaitHint; DWORD dwWaitHint; SERVICE_STATUS, SERVICE_STATUS, *LPSERVICE_STATUS; *LPSERVICE_STATUS
41、;For: 分类信息 From: 新闻【例【例9.7】p编写程序,查询服务编写程序,查询服务WebClientWebClient的状态,代码如下:的状态,代码如下:#include stdafx.h#include stdafx.h#include #include #include #include int _tmain(int argc, _TCHAR* argv)int _tmain(int argc, _TCHAR* argv) SC_HANDLE hSC; / SC_HANDLE hSC; / 服务管理器句柄服务管理器句柄SC_HANDLE handle;SC_HANDLE ha
42、ndle;/服务句柄服务句柄hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, SC_MANAGER_ALL_ACCESS);SC_MANAGER_ALL_ACCESS);if(hSC = NULL)if(hSC = NULL) printf( printf( 无法连接服务管理器!无法连接服务管理器!n);n);return 1;return 1; handle = :OpenService( hSC
43、, WebClient, SERVICE_ALL_ACCESS);handle = :OpenService( hSC, WebClient, SERVICE_ALL_ACCESS); For: 分类信息 From: 新闻接上接上if(handle = NULL)if(handle = NULL) printf( printf( 无法打开服务!无法打开服务!n);n);return 2;return 2; SERVICE_STATUS status;SERVICE_STATUS status; / / 获取服务的状态获取服务的状态 if(:QueryServiceStatus( handl
44、e, &status) = FALSE) if(:QueryServiceStatus( handle, &status) = FALSE) printf( printf( 获取服务状态错误获取服务状态错误n);n);return 3;return 3; switch(status.dwCurrentState) switch(status.dwCurrentState) case SERVICE_CONTINUE_PENDING:case SERVICE_CONTINUE_PENDING:printf(printf(恢复服务操作被挂起恢复服务操作被挂起n);n);break;break;ca
45、se SERVICE_PAUSE_PENDING:case SERVICE_PAUSE_PENDING:printf(printf(暂停服务操作被挂起暂停服务操作被挂起n);n);break;break;For: 分类信息 From: 新闻接上接上case SERVICE_PAUSED:case SERVICE_PAUSED:printf(printf(服务被暂停服务被暂停n);n);break;break;case SERVICE_RUNNING:case SERVICE_RUNNING:printf(printf(服务正在运行服务正在运行n);n);break;break;case S
46、ERVICE_START_PENDING:case SERVICE_START_PENDING:printf(printf(服务正在启动服务正在启动n);n);break;break;case SERVICE_STOP_PENDING:case SERVICE_STOP_PENDING:printf(printf(服务正在停止服务正在停止n);n);break;break;case SERVICE_STOPPED:case SERVICE_STOPPED:printf(printf(服务没有运行服务没有运行n);n);break;break;default:default:printf(pri
47、ntf(未知状态未知状态n);n);break;break; system(pause);system(pause);return 0;return 0; For: 分类信息 From: 新闻9.2.8 修改修改服务的服务的配置参数配置参数p调用调用ChangeServiceConfig ()ChangeServiceConfig ()函数可以修改指定服务的配置参数,函数原型如下:函数可以修改指定服务的配置参数,函数原型如下:BOOL WINAPI ChangeServiceConfig(BOOL WINAPI ChangeServiceConfig( _in SC_HANDLE hSer
48、vice, _in SC_HANDLE hService,/ / 服务句柄服务句柄 _in DWORD dwServiceType, _in DWORD dwServiceType,/ / 服务类型服务类型 _in DWORD dwStartType, _in DWORD dwStartType,/ / 服务启动类型服务启动类型 _in DWORD dwErrorControl, _in DWORD dwErrorControl,/ / 指定错误的严重程度指定错误的严重程度 _in LPCTSTR lpBinaryPathName,/ _in LPCTSTR lpBinaryPathName,
49、/ 服务的可执行文件的路径服务的可执行文件的路径 _in LPCTSTR lpLoadOrderGroup,/ _in LPCTSTR lpLoadOrderGroup,/ 服务所述的加载顺序组服务所述的加载顺序组 _out LPDWORD lpdwTagId, / _out LPDWORD lpdwTagId, /用于接收在参数用于接收在参数lpLoadOrderGrouplpLoadOrderGroup指定的组中的一个唯一指定的组中的一个唯一标记标记 _in LPCTSTR lpDependencies, / _in LPCTSTR lpDependencies, /包含服务名或加载顺序组
50、名的数组,指定服务的依包含服务名或加载顺序组名的数组,指定服务的依赖关系。数组中的服务和组必须在创建的服务之前被启动赖关系。数组中的服务和组必须在创建的服务之前被启动 _in LPCTSTR lpServiceStartName,/ _in LPCTSTR lpServiceStartName,/ 运行服务的账户名运行服务的账户名 _in LPCTSTR lpPassword, / _in LPCTSTR lpPassword, /参数参数lpServiceStartNamelpServiceStartName指定的账户的密码指定的账户的密码 _in LPCTSTR lpDisplayName
51、 / _in LPCTSTR lpDisplayName / 服务的显示名服务的显示名););For: 分类信息 From: 新闻【例【例9.8】p编写程序,将服务编写程序,将服务WebClientWebClient的启动状态设置为自动,代码如下:的启动状态设置为自动,代码如下:pp#include stdafx.h#include stdafx.hp#include #include p#include #include pppint _tmain(int argc, _TCHAR* argv)int _tmain(int argc, _TCHAR* argv)p pSC_HANDLE
52、hSC; / SC_HANDLE hSC; / 服务管理器句柄服务管理器句柄pSC_HANDLE handle;SC_HANDLE handle;/服务句柄服务句柄pphSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, SERVICE_CHANGE_CONFIG);hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, SERVICE_CHANGE_CONFIG);pif(hSC = NULL)if(hSC = NULL)p pprintf( printf
53、( 无法连接服务管理器!无法连接服务管理器!n);n);preturn 1;return 1;p phandle = :OpenService( hSC, WebClient, SERVICE_CHANGE_CONFIG);handle = :OpenService( hSC, WebClient, SERVICE_CHANGE_CONFIG);pif(handle = NULL)if(handle = NULL)p pprintf( printf( 无法打开服务!无法打开服务!n);n);preturn 2;return 2;p pFor: 分类信息 From: 新闻接上接上:Chang
54、eServiceConfig(handle, SERVICE_NO_CHANGE,:ChangeServiceConfig(handle, SERVICE_NO_CHANGE,SERVICE_AUTO_START,SERVICE_AUTO_START,/ / 修改服务为自动启动修改服务为自动启动NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL); NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL); :CloseServiceHandle(handle);:CloseServiceHandle(handle);
55、return 0;return 0; For: 分类信息 From: 新闻ChangeServiceConfig2()函数函数p调用调用ChangeServiceConfig2()ChangeServiceConfig2()函数可以修改指定服务的函数可以修改指定服务的可选配置参数,函数原型如下:可选配置参数,函数原型如下:BOOL WINAPI ChangeServiceConfig2(BOOL WINAPI ChangeServiceConfig2( _in SC_HANDLE hService, _in SC_HANDLE hService, / / 服务句柄服务句柄 _in DWOR
56、D dwInfoLevel, _in DWORD dwInfoLevel, / / 要修改的服务配置要修改的服务配置信息信息 _in LPVOID lpInfo _in LPVOID lpInfo / / 要修改的服务配置要修改的服务配置信息的新值,如果为信息的新值,如果为NULLNULL,则不修改,则不修改););For: 分类信息 From: 新闻【例【例9.9】p编写程序,将服务编写程序,将服务WebClientWebClient的描述信息设置为的描述信息设置为“WebClient“WebClient服务的描述信息服务的描述信息”,代码如下:,代码如下:#include stdafx
57、.h#include stdafx.h#include #include #include #include int _tmain(int argc, _TCHAR* argv)int _tmain(int argc, _TCHAR* argv) SC_HANDLE hSC; / SC_HANDLE hSC; / 服务管理器句柄服务管理器句柄SC_HANDLE handle;SC_HANDLE handle;/服务句柄服务句柄hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, hSC = :OpenSCManager( N
58、ULL, /*SERVICES_ACTIVE_DATABASE*/NULL, SERVICE_CHANGE_CONFIG);SERVICE_CHANGE_CONFIG);if(hSC = NULL)if(hSC = NULL) printf( printf( 无法连接服务管理器!无法连接服务管理器!n);n);return 1;return 1; handle = :OpenService( hSC, WebClient, SERVICE_CHANGE_CONFIG);handle = :OpenService( hSC, WebClient, SERVICE_CHANGE_CONFIG);i
59、f(handle = NULL)if(handle = NULL) printf( printf( 无法打开服务!无法打开服务!n);n);return 2;return 2; For: 分类信息 From: 新闻接上接上SERVICE_DESCRIPTION Description;SERVICE_DESCRIPTION Description;TCHAR szDescription1024;TCHAR szDescription1024;ZeroMemory(szDescription, 1024);ZeroMemory(szDescription, 1024);ZeroMemory(
60、&Description, sizeof(SERVICE_DESCRIPTION);ZeroMemory(&Description, sizeof(SERVICE_DESCRIPTION);lstrcpy(szDescription, _T(WebClientlstrcpy(szDescription, _T(WebClient服务的描述信息服务的描述信息););Description.lpDescription = szDescription;Description.lpDescription = szDescription;:ChangeServiceConfig2(handle, SER
61、VICE_CONFIG_DESCRIPTION, :ChangeServiceConfig2(handle, SERVICE_CONFIG_DESCRIPTION, &Description);&Description);:CloseServiceHandle(handle);:CloseServiceHandle(handle);return 0;return 0; For: 分类信息 From: 新闻结构体结构体SERVICE_DESCRIPTION typedef struct _SERVICE_DESCRIPTION typedef struct _SERVICE_DESCRIPT
62、ION LPTSTR lpDescription; LPTSTR lpDescription;/ / 服务描述信息字符串服务描述信息字符串 SERVICE_DESCRIPTION, SERVICE_DESCRIPTION, *LPSERVICE_DESCRIPTION *LPSERVICE_DESCRIPTION; ;For: 分类信息 From: 新闻9.3 开发开发Windows服务程序服务程序p9.3.1 9.3.1 创建创建ATLATL服务应用程序服务应用程序p9.3.2 9.3.2 安装安装和卸载和卸载ATLATL服务服务p9.3.3 9.3.3 设置服务的属性设置服务的属性Fo
63、r: 分类信息 From: 新闻9.3.1 创建创建ATL服务应用程序服务应用程序pATLATL(Active Template LibraryActive Template Library活动模板库)是微软开活动模板库)是微软开发的一组基于模板(发的一组基于模板(templatetemplate)的)的C+C+类。用于简化类。用于简化COMCOM(Component Object ModelComponent Object Model,组件对象模型)编程。,组件对象模型)编程。程序员可以使用程序员可以使用Visual C+Visual C+创建各种创建各种COMCOM对象、对象、OLEO
64、LE自动自动服务程序和服务程序和ActiveXActiveX控件。控件。pATLATL提供一个对象向导,使用它可以很快地建立对象的提供一个对象向导,使用它可以很快地建立对象的主要结构,从而使用户可以使用最少的手工编码来完成主要结构,从而使用户可以使用最少的手工编码来完成开发任务。由于篇幅所限,本书不对开发任务。由于篇幅所限,本书不对ATLATL技术的细节进技术的细节进行介绍,有兴趣的读者可以查阅相关资料学习。行介绍,有兴趣的读者可以查阅相关资料学习。For: 分类信息 From: 新闻创建创建ATL项目项目p在在Visual Studio 2008Visual Studio 2008中打开
65、中打开“新建项目新建项目”对话框,在对话框,在“项目类型项目类型”列表中,选择列表中,选择“Visual C+Visual C+”/ /“ATLATL”,然后在右侧的模板列表中选中然后在右侧的模板列表中选中“ALTALT项目项目”,如图,如图9.79.7所所示。示。For: 分类信息 From: 新闻ATL项目向导项目向导For: 分类信息 From: 新闻“应用程序配置应用程序配置”对话框对话框For: 分类信息 From: 新闻ATL服务解决方案中包含的项目服务解决方案中包含的项目pMyServiceMyService:应用程序(:应用程序(.exe.exe)类型的项目,用于生
66、成)类型的项目,用于生成ATLATL服务对应的可执行文件。服务对应的可执行文件。pMyServicePSMyServicePS:动态库(:动态库(.dll.dll)类型的项目,是服务程)类型的项目,是服务程序与客户端进行通信的代理序与客户端进行通信的代理- -存根(存根(proxy-stubproxy-stub),用),用于负责服务程序与客户端的通信。于负责服务程序与客户端的通信。For: 分类信息 From: 新闻9.3.2 安装安装和卸载和卸载ATL服务服务p生成项目后,得到生成项目后,得到MyService.exeMyService.exe。但是如何使它以服。但是如何使它以服务的形式
67、运行呢?打开命令行窗口,契切换到务的形式运行呢?打开命令行窗口,契切换到MyService.exeMyService.exe所在的目录下,执行如下命令安装服务。所在的目录下,执行如下命令安装服务。MyService /ServiceMyService /ServiceFor: 分类信息 From: 新闻安全软件的提示安全软件的提示For: 分类信息 From: 新闻查看新安装的服务查看新安装的服务For: 分类信息 From: 新闻卸载服务卸载服务p打开命令行窗口,切换到打开命令行窗口,切换到MyService.exeMyService.exe所在的目录下,执行如下命令卸载服务。所
68、在的目录下,执行如下命令卸载服务。MyService /unRegServerMyService /unRegServerFor: 分类信息 From: 新闻9.3.3 设置服务的属性设置服务的属性1 1设置服务名称设置服务名称2 2设置服务描述和启动方式设置服务描述和启动方式For: 分类信息 From: 新闻1设置服务名称设置服务名称CAtlServiceModuleT:RegisterAppId()CAtlServiceModuleT:RegisterAppId()函数的原型如下:函数的原型如下:inline HRESULT RegisterAppId(inline HRESUL
69、T RegisterAppId( bool bService = false / bool bService = false / 要注册为服务,必须使用要注册为服务,必须使用truetrue) throw( );) throw( );p如果执行成功,则返回如果执行成功,则返回S_OKS_OK;否则返回一个错误值。;否则返回一个错误值。For: 分类信息 From: 新闻重载重载RegisterAppId()函数函数HRESULT CMyServiceModule:RegisterAppId(bool bService = false) throw()HRESULT CMyServiceMo
70、dule:RegisterAppId(bool bService = false) throw() HRESULT hr = S_OK;HRESULT hr = S_OK;BOOL res = _super:RegisterAppId(bService); / BOOL res = _super:RegisterAppId(bService); / 调用父类的调用父类的RegisterAppId()RegisterAppId()函数函数if (bService) if (bService) if(IsInstalled() / if(IsInstalled() / 如果服务安装成功如果服务安装
71、成功 / / 以修改配置的权限打开服务控制器以修改配置的权限打开服务控制器SC_HANDLE hSCM = :OpenSCManager(NULL, NULL,SERVICE_CHANGE_CONFIG);SC_HANDLE hSCM = :OpenSCManager(NULL, NULL,SERVICE_CHANGE_CONFIG);SC_HANDLE hService = NULL;SC_HANDLE hService = NULL;if (hSCM = NULL)if (hSCM = NULL)hr = AtlHresultFromLastError();hr = AtlHresultF
72、romLastError();elseelse/ / 以修改配置的权限打开安装的服务以修改配置的权限打开安装的服务hService = :OpenService(hSCM, m_szServiceName, hService = :OpenService(hSCM, m_szServiceName, SERVICE_CHANGE_CONFIG);SERVICE_CHANGE_CONFIG);if (hService != NULL)if (hService != NULL):ChangeServiceConfig(hService, SERVICE_NO_CHANGE,:ChangeServi
73、ceConfig(hService, SERVICE_NO_CHANGE,SERVICE_AUTO_START,/ SERVICE_AUTO_START,/ 修改服务为自动启动修改服务为自动启动NULL, NULL, NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, NULL, NULL, NULL, NULL,m_szServiceName); / m_szServiceName); / 通过修改资源通过修改资源IDS_SERVICENAME IDS_SERVICENAME 修改服修改服务的显示名字务的显示名字 For: 分类信息 From:
74、新闻接上接上/ / 设置服务描述信息设置服务描述信息SERVICE_DESCRIPTION Description;SERVICE_DESCRIPTION Description;TCHAR szDescription1024;TCHAR szDescription1024;ZeroMemory(szDescription, 1024);ZeroMemory(szDescription, 1024);ZeroMemory(&Description, sizeof(SERVICE_DESCRIPTION);ZeroMemory(&Description, sizeof(SERVICE_DESCR
75、IPTION);lstrcpy(szDescription, _T(lstrcpy(szDescription, _T(我的第我的第1 1个服务个服务););Description.lpDescription = szDescription;Description.lpDescription = szDescription;:ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, :ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &Description);&De
76、scription);:CloseServiceHandle(hService);:CloseServiceHandle(hService); elseelsehr = AtlHresultFromLastError();hr = AtlHresultFromLastError();:CloseServiceHandle(hSCM);:CloseServiceHandle(hSCM); return hr;return hr; For: 分类信息 From: 新闻9.4 增加和使用组件增加和使用组件9.4.1 9.4.1 增加组件增加组件9.4.2 9.4.2 在客户端程序中使用组件类在客
77、户端程序中使用组件类For: 分类信息 From: 新闻9.4.1 增加组件增加组件在菜单中选择在菜单中选择“项目项目”/“”/“添加类添加类”,打开,打开“添加类添加类”窗口。在窗口窗口。在窗口左侧的左侧的“类别类别”列表中选择列表中选择“ATL”“ATL”,在右侧的,在右侧的“模板模板”列表中选择列表中选择“ATL“ATL简单对象简单对象”,如图,如图9.149.14所示。所示。For: 分类信息 From: 新闻“ATL简单对象向导简单对象向导”窗口窗口For: 分类信息 From: 新闻新添加的类新添加的类CMyMathFor: 分类信息 From: 新闻MyMath.
78、rgsHKCRHKCR MyService.MyMath.1 = s MyMath ClassMyService.MyMath.1 = s MyMath Class val AppID = s %APPID%val AppID = s %APPID% For: 分类信息 From: 新闻在组件类中添加函数在组件类中添加函数p在类视图窗口中右击接口在类视图窗口中右击接口IMyMathIMyMath,在弹出菜单中选择,在弹出菜单中选择“添加添加”/“”/“添加方法添加方法”,打开,打开“添加方添加方法向导法向导”窗口。假定添加一个求和函数窗口。假定添加一个求和函数SumSum,参照下面的方法添
79、加参数。,参照下面的方法添加参数。p(1 1)参数属性选中)参数属性选中inin,参数类型选择,参数类型选择 LONGLONG,参数名输入,参数名输入 a a,单击,单击“添加添加”按钮;按钮;p(2 2)参数属性选中)参数属性选中inin,参数类型选择,参数类型选择 LONGLONG,参数名输入,参数名输入 b b,单击,单击“添加添加”按钮;按钮;p(3 3)参数类型选择)参数类型选择 LONG*LONG*,参数属性选中,参数属性选中retvalretval,参数名输入,参数名输入 s s,单击,单击“添加添加”按钮;按钮;For: 分类信息 From: 新闻修改修改sum()函数的代
80、码函数的代码p打开打开 MyMath.cpp MyMath.cpp 文件,找到文件,找到 Sum Sum 方法方法修改修改sum()sum()函数的代码如下:函数的代码如下: STDMETHODIMP CMyMath:Sum(LONG a, LONG b, STDMETHODIMP CMyMath:Sum(LONG a, LONG b, LONG* s)LONG* s) *s = a + b; *s = a + b;return S_OK;return S_OK; For: 分类信息 From: 新闻MyService.idlpMyServiceMyService项目中还有一个自动生成的源
81、文件项目中还有一个自动生成的源文件MyService.idlMyService.idl,用,用于定义于定义MyServiceMyService服务的通用接口。在客户端程序中可以调用其中服务的通用接口。在客户端程序中可以调用其中定义的通用接口定义的通用接口。library MyServiceLiblibrary MyServiceLib importlib(stdole2.tlb);importlib(stdole2.tlb); uuid(07090083-8787-4EFB-8472-4B3F7F570304),uuid(07090083-8787-4EFB-8472-4B3F7F570304
82、),helpstring(MyMath Class)helpstring(MyMath Class) coclass MyMathcoclass MyMath default interface IMyMath;default interface IMyMath;For: 分类信息 From: 新闻9.4.2 在客户端程序中使用组件类在客户端程序中使用组件类p在生成在生成ATLATL服务应用程序时,除了服务应用程序时,除了exeexe文件外,还可以生成一个文件外,还可以生成一个tlbtlb文件,其中包含文件,其中包含COMCOM的类型信息。在客户端程序中使用的类型信息。在客户端程序中使用#
83、import#import语语句可以导入句可以导入tlbtlb文件,从而调用组件类,代码如下:文件,从而调用组件类,代码如下:#import tlb#import MyService.tlbMyService.tlbp因为要引用因为要引用MyServiceLibMyServiceLib库中的类和接口,需要使用下面的钱语库中的类和接口,需要使用下面的钱语句定义默认的命名空间为句定义默认的命名空间为MyServiceLibMyServiceLib:using namespace MyServiceLib;using namespace MyServiceLib;For: 分类信息 From:
84、新闻对客户端计算机进行配置对客户端计算机进行配置p在客户端程序中使用在客户端程序中使用ATLATL服务中的组件类时,有时会因为服务中的组件类时,有时会因为COMCOM安全验证的原安全验证的原因被拒绝访问,可以按照下面的步骤对客户端计算机进行配置。因被拒绝访问,可以按照下面的步骤对客户端计算机进行配置。p在在“运行运行”窗口中执行窗口中执行DCOMCNFGDCOMCNFG命令,打开命令,打开“组件服务组件服务”窗口。在左侧的窗口。在左侧的树结构中依次选择树结构中依次选择“控制台根目录控制台根目录”/“”/“计算机计算机”/“”/“我的电脑我的电脑”/“DCOM”/“DCOM配置配置”,可以在右侧
85、窗格种找到,可以在右侧窗格种找到MyServiceMyService组件,如图组件,如图9.19.18 8所示。所示。For: 分类信息 From: 新闻组件属性窗口组件属性窗口For: 分类信息 From: 新闻1初始化初始化COM环境环境pATLATL服务中的类是服务中的类是COMCOM组件类,因此在使用它之组件类,因此在使用它之前,要调用前,要调用CoInitialize()CoInitialize()函数初始化函数初始化COMCOM环境,环境,函数原型如下:函数原型如下: HRESULT CoInitialize( HRESULT CoInitialize( LPVOID pv
86、Reserved LPVOID pvReserved/ / 保留,必须为保留,必须为NULLNULL););p如果如果COMCOM库初始化成功,则函数返回库初始化成功,则函数返回S_OKS_OK,如果,如果返回返回S_FALSES_FALSE,则表示,则表示COMCOM库已经被初始化。库已经被初始化。For: 分类信息 From: 新闻2获取获取COM组件类的组件类的CLSIDp在调用在调用COMCOM组件类之前,需要调用组件类之前,需要调用CLSIDFromProgID()CLSIDFromProgID()函数获取函数获取COMCOM组件类的组件类的CLSIDCLSID,函数原型如下:,
87、函数原型如下: HRESULT CLSIDFromProgID( HRESULT CLSIDFromProgID( LPCOLESTR lpszProgID,/ LPCOLESTR lpszProgID,/ 要获取要获取CLSIDCLSID的的COMCOM组件类的组件类的ProgIDProgID字符字符串串 LPCLSID pclsid LPCLSID pclsid/ / 用于接收返回的用于接收返回的CLSIDCLSID););p如果成功获取指定如果成功获取指定COMCOM组件类的组件类的CLSIDCLSID,则函数返回,则函数返回S_OKS_OK;如果返;如果返回回CO_E_CLASSSTR
88、INGCO_E_CLASSSTRING,则表示指定的,则表示指定的ProgIDProgID字符串对应的字符串对应的CLSIDCLSID无无效;如果返回效;如果返回REGDB_E_WRITEREGDBREGDB_E_WRITEREGDB,则表示在将,则表示在将CLSIDCLSID写入注册表写入注册表中时发生错误。中时发生错误。For: 分类信息 From: 新闻3管理管理COM接口的智能指针接口的智能指针p在客户端程序中可以通过在客户端程序中可以通过COMCOM接口来访问组件类,使用智能指针类接口来访问组件类,使用智能指针类CComPtrCComPtr可以管理可以管理COMCOM接口。类接口
89、。类CComPtrCComPtr的定义代码如下:的定义代码如下:templatetemplateclass CComPtrclass CComPtrp例如定义一个管理例如定义一个管理IMyMathIMyMath接口的智能指针接口的智能指针pMyMathpMyMath,代码如下:,代码如下:CComPtr pMyMath;CComPtr pMyMath;For: 分类信息 From: 新闻4关闭关闭COM库库p在使用完在使用完COMCOM库之后,需要调用库之后,需要调用CoUninitialize()CoUninitialize()函数关闭函数关闭COMCOM库,函数原库,函数原型如下:型如
90、下: void CoUninitialize(void); void CoUninitialize(void);For: 分类信息 From: 新闻【例【例9.10】p编写客户端程序,调用编写客户端程序,调用ATLATL服务服务MyServiceMyService中类中类MyMathMyMath的的Sum()Sum()函数,代码如下:函数,代码如下:#include stdafx.h#include stdafx.h#include #include / / 注意,将下面的路径更改为注意,将下面的路径更改为MyService.tlbMyService.tlb文件所在的实际路径文件所在的实际
91、路径#import F:MyBookWindows#import F:MyBookWindows系统编程系统编程源代码源代码第章第章MyServiceMyServiceDebugMyService.tlbMyServiceMyServiceDebugMyService.tlbusing namespace MyServiceLib;using namespace MyServiceLib;int _tmain(int argc, _TCHAR* argv)int _tmain(int argc, _TCHAR* argv) / / 初始化初始化COMCOM环境环境CoInitialize(NU
92、LL);CoInitialize(NULL);CLSID clsid;CLSID clsid;HRESULT hr = CLSIDFromProgID(OLESTR(MyService.MyMath), HRESULT hr = CLSIDFromProgID(OLESTR(MyService.MyMath), &clsid); / &clsid); / 获取获取COMCOM组件类的组件类的CLSIDCLSID CComPtr pMyMath; / CComPtr pMyMath; / 智能指针智能指针 hr = pMyMath.CoCreateInstance(clsid); hr = pM
93、yMath.CoCreateInstance(clsid);/ / 创建创建pMyMathpMyMath的类实例的类实例 printf(1+2=%dn, pMyMath-Sum(1,2); / printf(1+2=%dn, pMyMath-Sum(1,2); / 调用类中的函数调用类中的函数 pMyMath.Release(); / pMyMath.Release(); / 释放智能指针释放智能指针 CoUninitialize();/ CoUninitialize();/ 关闭关闭COMCOM库库 system(pause); system(pause);return 0;return 0
94、; a aa aFor: 分类信息 From: 新闻9.5 Windows服务状态监视器实例服务状态监视器实例9.5.1 9.5.1 设计程序界面设计程序界面9.5.2 9.5.2 设计设计自定义类自定义类CServiceCService9.5.3 9.5.3 加载加载和监视服务和监视服务For: 分类信息 From: 新闻9.5.1 设计程序界面设计程序界面创建一个基于对话框的项目创建一个基于对话框的项目ServiceManagerServiceManager,在主对话框,在主对话框IDD_SERVICEMANAGER_DIALOGIDD_SERVICEMANAGER_DIALOG中
95、参照表中参照表9.159.15添加控件,并为其定义成员变量。添加控件,并为其定义成员变量。控件类型控件ID成员变量的定义说明List ControlIDC_LIST1CListCtrl m_ServiceList;用于显示监视服务的列表Check BoxIDC_CHECK1int m_check;“检测服务状态,自动启动服务”复选框Progress BarIDC_PROGRESS1CProgressCtrl m_Progress;用于显示启动和停止服务的进度的进度条ButtonIDC_BUTTON_REFRESH(无)“刷新”按钮ButtonIDC_BUTTON_CLOSE(无)“关闭”按钮F
96、or: 分类信息 From: 新闻9.5.2 设计设计自定义类自定义类CServiceclass CServiceclass CService public:public:CService(void);CService(void); string Name; string Name;/服务名服务名string Desc;string Desc;/ / 服务密描述服务密描述 SERVICE_STATUS Status; SERVICE_STATUS Status;/ / 服务状态服务状态bool exist;bool exist;/服务是否服务是否存在存在SC_HANDLE hSC;SC_H
97、ANDLE hSC;/ / 服务管理器句柄服务管理器句柄SC_HANDLE handle;SC_HANDLE handle;/服务句柄服务句柄public:public:CService(void);CService(void); void GetStatus(); void GetStatus();/ / 获取服务状态获取服务状态void StartService();void StartService();/ / 启动服务启动服务void StopService();void StopService();/ / 停止服务停止服务;For: 分类信息 From: 新闻GetStatus(
98、)函数函数void CService:GetStatus()void CService:GetStatus() exist = true; exist = true; / / 打开服务管理对象打开服务管理对象if(hSC = NULL)if(hSC = NULL)hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, SC_MANAGER_ALL_ACCESS);SC_MANAGER_ALL_ACCESS
99、);/打开服务打开服务handle = :OpenService( hSC, Name.c_str(), SERVICE_ALL_ACCESS);handle = :OpenService( hSC, Name.c_str(), SERVICE_ALL_ACCESS);if(handle = NULL)if(handle = NULL) exist= false; exist= false; return;return; / / 获取服务的状态获取服务的状态 if(:QueryServiceStatus( handle, &Status) = FALSE) if(:QueryServiceSt
100、atus( handle, &Status) = FALSE) TRACE( TRACE( 获取服务状态错误获取服务状态错误););return;return; For: 分类信息 From: 新闻StartService ()函数函数void CService:StartService()void CService:StartService() SERVICE_STATUS status;SERVICE_STATUS status;if( :StartService( handle, NULL, NULL) = if( :StartService( handle, NULL, NULL)
101、 = FALSE)FALSE) TRACE( TRACE( 无法启动服务!无法启动服务!););return ;return ; For: 分类信息 From: 新闻StopService()函数函数void CService:StopService()void CService:StopService() SERVICE_STATUS status;SERVICE_STATUS status;if( :ControlService( handle, if( :ControlService( handle, SERVICE_CONTROL_STOP, &status) = FALSE)SE
102、RVICE_CONTROL_STOP, &status) = FALSE) TRACE( TRACE( 无法停止服务!无法停止服务!););return;return; For: 分类信息 From: 新闻9.5.3 加载加载和监视服务和监视服务void CServiceManagerDlg:Init_Services()void CServiceManagerDlg:Init_Services() SC_HANDLE hSC; SC_HANDLE hSC;hSC = :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, hSC =
103、 :OpenSCManager( NULL, /*SERVICES_ACTIVE_DATABASE*/NULL, SC_MANAGER_ALL_ACCESS);SC_MANAGER_ALL_ACCESS);if(hSC = NULL) if(hSC = NULL) TRACE( TRACE( 无法打开服务管理对象!无法打开服务管理对象!););exit(0);exit(0); service_arr0.Name =WebClient;service_arr0.Name =WebClient;service_arr0.Desc = WebClient;service_arr0.Desc = WebClient;service_arr0.hSC = hSC;service_arr0.hSC = hSC;service_arr1.Name =MyService;service_arr1.Name =MyService;service_arr1.Desc = MyService;service_arr1.Desc = MyService;service_arr1.hSC = hSC;service_arr1.hSC = hSC;