首页
社区
课程
招聘
[原创]Windows系统程序设计之系统服务
2006-7-18 10:25 15550

[原创]Windows系统程序设计之系统服务

2006-7-18 10:25
15550
Windows系统程序设计之系统服务

【作者】北极星2003
【来源】看雪技术论坛(bbs.pediy.com)
【时间】2006-7-18

WIN32服务管理器
1.设计目标
        设计简易的Win32服务管理器,实现基本的WIN32服务管理功能,包括启动、停止、添加、删除、暂停、恢复和设置自动、手动、禁用启动类型。

2.设计思路


设计思路比较简单:
        (1)枚举服务
        (2)服务控制(启动、停止……)
        (3)排序(枚举出来的服务的以服务名排序的,而系统默认的服务管理是以显示名称排序的)
3.难点
        (1)需要注意 OpenSCManager 时权限设置
        (2)在对ENUM_SERVICE_STATUS结构数组进行排序时并不能直接对其本身进行排序,需要建立一个相应的索引数组。(这里使用插入排序算法)

4.详细设计
// CSM.h
#ifndef _CSM_H
#define _CSM_H

#ifndef _WINSVC_H
#include <Winsvc.h>
#define _WINSVC_H
#endif

#include <stdlib.h>

const int MAX_SERVICE_NUM = 512 ;

class CSM {
public:
	DWORD		dwSerNum ;
	UINT		nSerIndex[MAX_SERVICE_NUM];
	ENUM_SERVICE_STATUS SerStatus[MAX_SERVICE_NUM] ;

public:
	CSM () {}
	~CSM () {}
	
public:
	// 枚举服务
	BOOL EnumWin32Service ( ) ;
	
	// 启动服务
	BOOL StartWin32Service ( UINT nIndex ) ;
	
	// 停止服务
	BOOL StopWin32Service ( UINT nIndex ) ;
	
	// 暂停服务
	BOOL PauseWin32Service ( UINT nIndex ) ;
	
	//恢复服务
	BOOL ContinueWin32Service ( UINT nIndex ) ;
	
	// 服务启动类型--自动
	BOOL SetAutoStartType ( UINT nIndex ) ;

	// 服务启动类型--手动
	BOOL SetManualStartType ( UINT nIndex ) ;

	// 服务启动类型--禁用
	BOOL SetDisableStartType ( UINT nIndex ) ;

	// 取得服务的启动类型
	UINT GetServiceStartType ( UINT nIndex ) ;
	
	// 加载服务
	BOOL AddWin32Service ( LPCSTR lpServiceName, LPCSTR lpDisplayName, LPSTR lpPathName ) ;

	// 卸载服务
	BOOL DeleteWin32Service ( UINT nIndex ) ;
	
protected:
	// 取得指定索引的服务的句柄
	SC_HANDLE GetServiceByIndex ( UINT nIndex ) ;

	// 以显示名称排序
	void SortByDisplayName () ;

	// 自定义字符串比较
	int MyStrCmp ( LPSTR FirStr, LPSTR SecStr ) ;
} ;

#endif


//CSM.cpp
#include "stdafx.h"
#include "CSM.h"

// 枚举服务
BOOL CSM::EnumWin32Service ( )
{
	SC_HANDLE hSCManager = OpenSCManager ( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE|GENERIC_READ ) ;
	if ( hSCManager == NULL )
	{
		return FALSE ;
	}	
	
	DWORD dwBufSize = 512 * sizeof(ENUM_SERVICE_STATUS) ;  
	DWORD dwBytesNeeded, lpResumeHandle = 0 ;
	if ( !EnumServicesStatus(hSCManager, SERVICE_WIN32, SERVICE_STATE_ALL, \
		SerStatus, dwBufSize, &dwBytesNeeded, &dwSerNum, &lpResumeHandle ) )
	{
		return FALSE ;
	}
	
	SortByDisplayName () ;
	CloseServiceHandle ( hSCManager ) ;
	return TRUE ;
}

// 启动服务
BOOL CSM::StartWin32Service ( UINT nIndex )
{
	SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	if ( !StartService ( hSCService, 0, NULL ) )
	{
		CloseServiceHandle ( hSCService ) ; 
		return FALSE ;
	}
	
	CloseServiceHandle ( hSCService ) ; 
	return TRUE ;
}

// 停止服务
BOOL CSM::StopWin32Service ( UINT nIndex )
{
	SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	if ( !ControlService ( hSCService, SERVICE_CONTROL_STOP, &(SerStatus[nIndex].ServiceStatus) ) )
	{
		CloseServiceHandle ( hSCService ) ; 
		return FALSE ;
	}
	
	CloseServiceHandle ( hSCService ) ; 
	return TRUE ;
}

// 暂停服务
BOOL CSM::PauseWin32Service ( UINT nIndex )
{
	SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	if ( !ControlService ( hSCService, SERVICE_CONTROL_PAUSE, &(SerStatus[nIndex].ServiceStatus) ) )
	{
		CloseServiceHandle ( hSCService ) ; 
		return FALSE ;
	}
	
	CloseServiceHandle ( hSCService ) ; 
	return TRUE ;
}

//恢复服务
BOOL CSM::ContinueWin32Service ( UINT nIndex )
{
	SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	if ( !ControlService ( hSCService, SERVICE_CONTROL_CONTINUE, &(SerStatus[nIndex].ServiceStatus) ) )
	{
		CloseServiceHandle ( hSCService ) ; 
		return FALSE ;
	}
	
	CloseServiceHandle ( hSCService ) ; 
	return TRUE ;
}

// 服务启动类型--自动
BOOL CSM::SetAutoStartType ( UINT nIndex )
{
	SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	if ( !ChangeServiceConfig( hSCService, SERVICE_NO_CHANGE, \
		SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)  )
	{
		CloseServiceHandle ( hSCService ) ; 
		return FALSE ;
	}
	
	CloseServiceHandle ( hSCService ) ; 
	return TRUE ;
}

// 服务启动类型--手动
BOOL CSM::SetManualStartType ( UINT nIndex )
{
	SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	if ( !ChangeServiceConfig( hSCService, SERVICE_NO_CHANGE, \
		SERVICE_DEMAND_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)  )
	{
		CloseServiceHandle ( hSCService ) ; 
		return FALSE ;
	}
	
	CloseServiceHandle ( hSCService ) ; 
	return TRUE ;
}

// 服务启动类型--禁用
BOOL CSM::SetDisableStartType ( UINT nIndex )
{
	SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	if ( !ChangeServiceConfig( hSCService, SERVICE_NO_CHANGE, \
		SERVICE_DISABLED, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)  )
	{
		CloseServiceHandle ( hSCService ) ; 
		return FALSE ;
	}
	
	CloseServiceHandle ( hSCService ) ; 
	return TRUE ;
}	

// 取得服务的启动类型
UINT CSM::GetServiceStartType ( UINT nIndex )
{
	SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	
	LPQUERY_SERVICE_CONFIG lpServiceConfig = (LPQUERY_SERVICE_CONFIG)new BYTE[1024] ;
	DWORD dwByteNeeded ;
	if ( !QueryServiceConfig ( hSCService, lpServiceConfig, 1024, &dwByteNeeded ) )
	{
		CloseServiceHandle ( hSCService ) ; 
		return 0 ;
	}
	
	UINT nServiceType = 0 ;
	switch ( lpServiceConfig->dwStartType )
	{
	case SERVICE_AUTO_START:	nServiceType = 1 ;	break ;
	case SERVICE_DEMAND_START:	nServiceType = 2 ;	break ;
	case SERVICE_DISABLED:		nServiceType = 3 ;	break ;
	default:					nServiceType = 4 ;
	}
	
	CloseServiceHandle ( hSCService ) ; 
	delete lpServiceConfig ;
	return nServiceType ;
}

// 加载服务
BOOL CSM::AddWin32Service ( LPCSTR lpServiceName, LPCSTR lpDisplayName, LPSTR lpPathName )
{
	SC_HANDLE hSCManager = OpenSCManager ( NULL, NULL, SC_MANAGER_CREATE_SERVICE ) ;
	if ( hSCManager == NULL )
	{
		return FALSE ;
	}
	
	SC_HANDLE hSCService =  CreateService ( hSCManager, lpServiceName, lpDisplayName, \
		SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \
		SERVICE_ERROR_NORMAL, lpPathName, NULL, NULL, NULL, NULL, NULL );
	if ( hSCService == NULL )
	{
		DWORD dwErrorCode = GetLastError () ;
		CloseServiceHandle ( hSCManager ) ;
		return FALSE ;
	}
	
	CloseServiceHandle ( hSCService ) ;
	CloseServiceHandle ( hSCManager ) ;
	return TRUE ;
}

// 卸载服务
BOOL CSM::DeleteWin32Service ( UINT nIndex )
{
	SC_HANDLE	hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;
	BOOL		bRet = DeleteService ( hSCService ) ;
	DWORD		dwErrorCode = GetLastError () ;
	CloseServiceHandle ( hSCService ) ;
	return bRet ;
}

// 取得指定索引的服务的句柄
SC_HANDLE CSM::GetServiceByIndex ( UINT nIndex )
{
	SC_HANDLE hSCManager = OpenSCManager ( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE|GENERIC_READ ) ;
	if ( hSCManager == NULL )
	{
		return NULL ;
	}
	
	SC_HANDLE hSCService = OpenService ( hSCManager, SerStatus[nIndex].lpServiceName, SERVICE_ALL_ACCESS ) ;
	CloseServiceHandle ( hSCManager ) ;
	return hSCService ;	
}

// 以显示名称排序
void CSM::SortByDisplayName ()
{
	memset ( nSerIndex, 0, sizeof(nSerIndex) ) ;
	
	for ( int i = 1; i < dwSerNum; i++ )
	{
		for ( int j = i-1; j >= 0; j-- )
		{
			if ( MyStrCmp ( SerStatus[i].lpDisplayName, SerStatus[nSerIndex[j]].lpDisplayName ) > 0 )
				break ;
			else
				nSerIndex[j+1] = nSerIndex[j] ;
		}
		nSerIndex[j+1] = i ;
	}
}

// 自定义字符串比较
int CSM::MyStrCmp ( LPSTR FirStr, LPSTR SecStr )
{
	char ChA, ChB ;
	UINT nIndex = 0 ;
	
	while ( true )
	{
		ChA = FirStr[nIndex] > 'Z' ? ( FirStr[nIndex] - 0x20 ) : FirStr[nIndex] ;
		ChB = SecStr[nIndex] > 'Z' ? ( SecStr[nIndex] - 0x20 ) : SecStr[nIndex] ;
		
		if ( ChA == '\0' && ChB == '\0' )
			return 0 ;
		else if ( ChA == '\0' )
			return -1 ;
		else if ( ChB == '\0' )
			return 1 ;
		
		if ( ChA > ChB )
			return 1 ;
		else if ( ChA < ChB )
			return -1 ;
		
		nIndex++ ;
	} 	
}


5.遇到的困难
        这个软件相对比较简单,需要注意的是建立索引后的排序。

6.总结(心得)
        增进对WIN32服务管理方式的了解。原本还想写个服务,由于最近较忙且资料实在太多就不写了。在参考文献中列举了一些关于服务的比较优秀的文章,其中还有相应的源代码可以下载。

【参考文献】
[1]. Beginner’s introductory guide to writing, installing, starting, stopping NT services
     http://www.codeproject.com/system/serviceskeleton.asp
[2]. CServiceHelper
     http://www.codeproject.com/system/cservicehelper.asp
[3]. Kmd教程2-服务
     http://211.90.241.130:22366/view.asp?file=321
[4]. Wind32位程序设计初步之服务
     http://www.webstudy8.com/web/net/209/0651108404367523.asp

【版权声明】必须注明原创于看雪技术论坛(bbs.pediy.com) 及作者,并保持文章的完整性。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
点赞7
打赏
分享
最新回复 (23)
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
Aker 4 2006-7-18 10:30
2
0
要是顺便说一下系统服务实现细节就好了
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
WAKU 7 2006-7-18 10:40
3
0
义无反顾的支持!
雪    币: 234
活跃值: (370)
能力值: ( LV9,RANK:530 )
在线值:
发帖
回帖
粉丝
lnn1123 13 2006-7-18 11:00
4
0
学习:)--
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xszhou 2006-7-18 11:02
5
0
最初由 北极星2003 发布
Windows系统程序设计之系统服务

【作者】北极星2003
【来源】看雪技术论坛(bbs.pediy.com)
【时间】2006-7-18
........

内容和标题不符,没涉及到具体的service编程,也没讲service的工作原理,其实jeffrey richter的书《Programming Server-Side Applications for Microsoft Windowsr 2000》已经把service讲的非常清楚了,包括各种io模型以及iocp等。
强烈推荐此书!
http://www.dfm24.com.cn/xszhou/Programming Server-Side Applications for Microsoft Windows 2000.rar
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 25 2006-7-18 11:26
6
0
最初由 xszhou 发布
内容和标题不符,没涉及到具体的service编程,也没讲service的工作原理,其实jeffrey richter的书《Programming Server-Side Applications for Microsoft Windowsr 2000》已经把service讲的非常清楚了,包括各种io模型以及iocp等。
强烈推荐此书!
http://www.dfm24.com.cn/xszhou/Programming Server-Side Applications for Microsoft Windows 2000.rar


我的目标是作为实例,如果有难点都会进行相关的阐述
但看我文章的前提是要有相关方面的基础知识,

至于你说的ICO,IOCP,不在这篇文章的范围内,我在其他篇幅中也有这些方面的实例程序及相关介绍

如果觉得这个标题不够恰当,这个不是问题,大家定个比较合适的

不过有一点,这里指的是Win32系统服务,而不是C/S中的服务,这也是有区别的
雪    币: 236
活跃值: (35)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
误入楼台 1 2006-7-18 14:04
7
0
支持 北极星的好东西
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sunbaiy 2006-7-18 15:35
8
0
不错!

建议加点内容:加一个编辑框,每选中一个服务时,介绍其主要功能、所起的作用,安全方面的问题,用词要简洁,用户看看这些信息就会立即作出决定,是自动启动、手动还是取消该服务,这样就可变成一个好帮手。
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 17 2006-7-18 16:48
9
0
支持,不过我不会C
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dwing 1 2006-7-18 20:00
10
0
这类工具已经有不少了,建议加入"高亮显示非操作系统服务"的实用功能.
雪    币: 2367
活跃值: (756)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
小虾 10 2006-7-18 22:10
11
0
北极星兄弟高产。
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
prince 16 2006-7-19 13:22
12
0
对不住北极星兄弟了,我收到你邮件后突然有急事去了外地,今天才回来,事发突然,完全把你的事情忘到脑后去了,幸好你解决了问题,这里跟你说声抱歉!
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
彪得榜 2006-7-20 10:07
13
0
不错
多多指教
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 25 2006-7-20 15:04
14
0
最初由 sunbaiy 发布
不错!

建议加点内容:加一个编辑框,每选中一个服务时,介绍其主要功能、所起的作用,安全方面的问题,用词要简洁,用户看看这些信息就会立即作出决定,是自动启动、手动还是取消该服务,这样就可变成一个好帮手。


最初由 dwing 发布
这类工具已经有不少了,建议加入"高亮显示非操作系统服务"的实用功能.


多谢两位建议,我有空会加上去的
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 25 2006-7-20 15:05
15
0
最初由 prince 发布
对不住北极星兄弟了,我收到你邮件后突然有急事去了外地,今天才回来,事发突然,完全把你的事情忘到脑后去了,幸好你解决了问题,这里跟你说声抱歉!


你太客气了,前段时间有点忙,后来空了也就解决了.
雪    币: 156
活跃值: (23)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
sbright 2 2006-7-20 20:22
16
0
非常支持北极星大哥把参考的文献也列出来.....要能把解决问题遇到的困难说说,....就...
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
joyzengli 2006-8-7 18:00
17
0
渴望里面的知识
雪    币: 139
活跃值: (111)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
bookworm 3 2006-8-8 09:27
18
0
关键是如何调试,这才是难点,因为它们和普通的程序不同。如何写service的例子程序上google一查有很多,请多介绍相关的调试排错技巧。
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 25 2006-8-8 13:57
19
0
最初由 bookworm 发布
关键是如何调试,这才是难点,因为它们和普通的程序不同。如何写service的例子程序上google一查有很多,请多介绍相关的调试排错技巧。


就是因为这部分内容网上太多,所以我就没有介绍如何写服务,只写了这个软件

另外对于如何写服务,在参考资料中列举了一些我觉得不错的资料

其实我做的这个软件本身比较简单,利用API从系统服务数据库中读取信息,或许有时间的时候我可以介绍些关于服务的原理性东西

上次遇到的问题,VC6.0本身的问题,一些莫名奇妙的问题,后来发现在clear原有的编译信息,再重新编译的话就可以了
雪    币: 744
活跃值: (4025)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2006-8-20 13:37
20
0
顶一下........
雪    币: 216
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
薄冰 2006-10-8 16:37
21
0
WINXP SP2下测试,服务能够添加,无法运行,“自动,手动,禁用”等状态修改功能正常,还望查找下何处出现故障
雪    币: 117
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无奈无赖 2006-11-12 19:10
22
0
个人感觉,这个例子,或者说这篇文章只是介绍了我们写这样一个程序需要使用哪几个API.

如果能介绍一下这几个API的参数各表示什么,在使用中有什么需要注意的问题就更完美了.虽然这些在MSDN上也能查到,但一是由于那个是英文,二是由于在实际使用中还是存在一些问题.所以简要的介绍一下还是有必要的.

这是为出这本书而写的文章,需要的是更详细的讲解,而不是一段例程.

纯属个人看法.
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sharey 2006-11-23 11:15
23
0
好文章,支持!
雪    币: 203
活跃值: (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lx6636 2006-11-29 20:23
24
0
学习下。唉,来了这里看帖,才知道牛人一堆又一堆
游客
登录 | 注册 方可回帖
返回