先说明,本文不是编写服务,而是编程控制已有的服务。
服务是一种程序类型,它在后台运行,服务程序通常可以在本地和通过网络为用户提供一些功能。服务程序可能是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)