Windows服务编程

先说明,本文不是编写服务,而是编程控制已有的服务。

服务是一种程序类型,它在后台运行,服务程序通常可以在本地和通过网络为用户提供一些功能。服务程序可能是EXE程序,具有其单独的进程,也有可能是DLL文件依附于某个进程,更有可能是SYS文件而处于系统的内核之中。

在Windows下,可以在“我的电脑”上单击鼠标右键,然后再弹出的菜单上选择“管理”,打开“计算机管理工具”,单击左面树形列表的“服务和应用程序”会打开子列表,选择“服务”,则在右侧出现服务列表项。也可以直接在“运行”窗口输入“services.msc”,打开服务管理器。服务管理器主要用于显示系统中已经存在的应用程序服务,显示对服务的描述,还可以控制服务的启动状态和启动方式。服务管理器界面如下图示:


服务编程常用API如下:

1. 打开服务管理器

SC_HANDLEOpenSCManager(
 LPCTSTR lpMachineName,//指向欲打开服务控制器数据库的目标主机名,本机则设置为NULL
LPCTSTRlpDatabaseName,//指向目标主机SCM数据库名字字符串
DWORD dwDesiredAccess//指定对SCM数据库的访问权限
);

2. 关闭服务句柄

BOOL CloseServiceHandle(
SC_HANDLEhSCObject//要关闭的服务或服务管理器句柄
);

3.服务的枚举

BOOL EnumServicesStatus(
  SC_HANDLE hSCManager,//OpenSCManager函数返回的句柄
  DWORD dwServiceType,//指定枚举服务类型
  DWORD dwServiceState,//枚举指定状态的服务
  LPENUM_SERVICE_STATUS lpServices,//结构体指针
  DWORD cbBufSize,//指定缓冲区大小
  LPDWORD pcbBytesNeeded,//返回实际使用的内存空间大小
  LPDWORD lpServicesReturned,//返回枚举服务的个数
  LPDWORD lpResumeHandle//返回枚举是否成功
);

4.打开指定服务

SC_HANDLEOpenService(
  SC_HANDLE hSCManager,//指定由OpenSCManager函数打开的服务句柄
  LPCTSTR lpServiceName,//指定要打开的服务名称
  DWORD dwDesiredAccess//打开服务的访问权限,为了方便,可指定为SC_MANAGER_ALL_ACCESS。
);

5.启动服务

BOOL StartService(
  SC_HANDLE hService,//指定要启动服务的句柄,该句柄由OpenService函数返回
  DWORD dwNumServiceArgs,//指向启动服务所需的参数个数
  LPCTSTR* lpServiceArgVectors//指向启动服务的参数
);

6.停止服务

BOOL ControlService(
  SC_HANDLE hService,//指定一个由OpenService打开的服务句柄
  DWORD dwControl,//指定要发送的控制码
  LPSERVICE_STATUS lpServiceStatus//返回服务的状态
);

ControlService()可以对服务进行多种控制,每种控制操作对应一种控制码。当要停止服务时,使用的控制码是SERVICE_CONTROL_STOP。

下面我们就写一个工程,实现电脑上Win32程序服务与驱动服务的分别展示,并且可以停止或者启动其中指定的服务。

用MFC搭建一个有如下界面的Dialog程序:


每个控件的作用相信大家都看得出来,界面方面的知识就不一一介绍了,直接上关键的控制代码。

其中CListCtrl控件的初始化可以参考注册表操作那篇博客。

实现服务枚举的代码如下:

VOID CMyDlg::ShowServiceList(DWORD dwServiceType)//参数是要枚举的服务类型
{
	m_ServiceList.DeleteAllItems();
	//打开服务管理器
	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if(NULL == hSCM)
	{
		AfxMessageBox("Open SCManager Error!");
		return;
	}

	DWORD ServiceCount = 0;
	DWORD dwSize = 0;
	LPENUM_SERVICE_STATUS lpInfo;

	//第一次调用
	BOOL bRet = EnumServicesStatus(hSCM,
				dwServiceType, SERVICE_STATE_ALL,
				NULL,0,&dwSize,
				&ServiceCount,NULL);

	/*
	由于没有给定接收服务列表的缓冲区,这里必定会调用失败
	失败的返回值时ERROR_MORE_DATA
	说明需要更大的缓冲区来保存数据
	*/

	if(!bRet && GetLastError() == ERROR_MORE_DATA)
	{
		//分配缓冲区保存服务列表
		lpInfo = (LPENUM_SERVICE_STATUS)(new BYTE[dwSize]);
		bRet = EnumServicesStatus(hSCM,
				dwServiceType, SERVICE_STATE_ALL,
				(LPENUM_SERVICE_STATUS)lpInfo,
				dwSize,&dwSize,
				&ServiceCount,NULL);
		if(!bRet)
		{
			CloseServiceHandle(hSCM);
			return;
		}

		//逐个获取数据,添加至列表控件
		for(DWORD i = 0; i < ServiceCount; ++i)
		{
			CString str;
			m_ServiceList.InsertItem(i, lpInfo[i].lpServiceName);
			m_ServiceList.SetItemText(i, 1, lpInfo[i].lpDisplayName);
			switch(lpInfo[i].ServiceStatus.dwCurrentState)
			{
			case SERVICE_PAUSED:
				{
					m_ServiceList.SetItemText(i, 2, "暂停");
					break;
				}
			case SERVICE_STOPPED:
				{
					m_ServiceList.SetItemText(i, 2, "停止");
					break;
				}
			case SERVICE_RUNNING:
				{
					m_ServiceList.SetItemText(i, 2, "运行");
					break;
				}
			default:
				{
					m_ServiceList.SetItemText(i, 2, "其它");
				}
			}
		}

		//释放申请的空间
		delete lpInfo;
	}

	//关闭服务管理器句柄
	CloseServiceHandle(hSCM);
}

启动服务的代码:

void CMyDlg::OnBtnStart() 
{
	//选择服务的索引
	POSITION Pos = m_ServiceList.GetFirstSelectedItemPosition();
	int nSelect = -1;

	while(Pos)
	{
		nSelect = m_ServiceList.GetNextSelectedItem(Pos);
	}

	if(-1 == nSelect)
	{
		AfxMessageBox("请选择要启动的服务");
		return;
	}

	//获取选择的服务的服务名
	char szServiceName[MAXBYTE] = {0};
	m_ServiceList.GetItemText(nSelect, 0, szServiceName, MAXBYTE);

	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if(NULL == hSCM)
	{
		AfxMessageBox("Open SCManager Eorror");
		return;
	}

	//打开指定的服务
	SC_HANDLE hCService = OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);

	//启动服务
	BOOL bRet = StartService(hCService, 0, NULL);
	if(bRet == TRUE)
	{
		m_ServiceList.SetItemText(nSelect, 2, "运行");
	}else{
		AfxMessageBox("启动失败");
	}

	CloseServiceHandle(hCService);
	CloseServiceHandle(hSCM);
	
}

停止服务的代码:

void CMyDlg::OnBtnStop() 
{
	//选择服务的索引
	POSITION Pos = m_ServiceList.GetFirstSelectedItemPosition();
	int nSelect = -1;

	while(Pos)
	{
		nSelect = m_ServiceList.GetNextSelectedItem(Pos);
	}

	if(-1 == nSelect)
	{
		AfxMessageBox("请选择要停止的服务");
		return;
	}
	
	//获取选择的服务的服务名
	char szServiceName[MAXBYTE] = {0};
	m_ServiceList.GetItemText(nSelect, 0, szServiceName, MAXBYTE);
	//
	SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if(NULL == hSCM)
	{
		AfxMessageBox("Open SCManager Eoor");
		return;
	}

	//打开指定的服务
	SC_HANDLE hSCService = OpenService(hSCM, szServiceName, SERVICE_ALL_ACCESS);
	SERVICE_STATUS ServiceStatus;
	//停止服务
	BOOL bRet = ControlService(hSCService, SERVICE_CONTROL_STOP, &ServiceStatus);
	if(bRet == TRUE)
	{
		m_ServiceList.SetItemText(nSelect, 2, "停止");
	}else{
		AfxMessageBox("服务停止失败");
	}

	CloseServiceHandle(hSCService);
	CloseServiceHandle(hSCM);
}

最后再亲情奉上本项目源码供大家参考,当然,我得收5积分的敲代码辛苦费。可以在我上传的资源上查:服务编程(blog)




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值