全局变量和函数声明
//第一个服务
void WINAPI ServiceMain();
void WINAPI ServiceHandler(DWORD dwOpcode);
TCHAR szServiceName[] = _T("ServiceTest");
//第二个服务
void WINAPI ServiceMain1();
void WINAPI ServiceHandler1(DWORD dwOpcode);
TCHAR szServiceName1[] = _T("ServiceTest1");
//
BOOL bInstall;
SERVICE_STATUS_HANDLE hServiceStatus;
SERVICE_STATUS status;
DWORD dwThreadID;
一、服务程序实现:
对于Service程序来说,它一般又由以下三部分组成:main(),ServiceMain()和Handler()
如果有多个服务,则必须要有多对的ServiceMain()和Handler()对应函数
1、main()
服务程序的入口与普通程序一样也是从main()开始,但不同的是服务程序的main极为简单,因为它只
负责创建分派表并启动控制分派机,其代码如下:
void main()
{
SERVICE_TABLE_ENTRY st[] =
{
{ szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ szServiceName1, (LPSERVICE_MAIN_FUNCTION)ServiceMain1 },
{ NULL, NULL } //最好必须以{NULL, NULL}结尾
};
//启动服务的控制分派机线程
if (!::StartServiceCtrlDispatcher(st))
{
……
}
}
main()是服务程序的主线程,当servie control manager开始一个Service进程时,它总是等待这个
服务程序去调用StartServiceCtrlDispatcher()函数。当执行服务时main()时将会调用ServiceMain
函数,当ServiceMain执行完毕或者发生错误时StartServiceCtrlDispatcher函数返回,然后主进程终止。
2. ServiceMain():服务的真正入口
ServiceMain()是服务程序的真正入口点,它主要完成以下功能,首先注册一个Handler去处理控制程序
或控制面板,服务的控制要求,比如 启动,停止,暂停,重启等,其次就是实现我们的功能操作,其实
现代码如下:
VOID WINAPI ServiceMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
DWORD status = 0;
DWORD specificError = 0xfffffff;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
//调用RegisterServiceCtrlHandler()注册一个ServiceHandler函数用来处理程序对Service的
//控制要求
hStatus = RegisterServiceCtrlHandler("ServiceName",(LPHANDLER_FUNCTION)ServiceHandler);
if (hStatus==0)
return;
// Handle error condition
status = GetLastError();
if (status!=NO_ERROR)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
ServiceStatus.dwWin32ExitCode = status;
ServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// Initialization complete - report running status
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus, &ServiceStatus);
//启动自己的工作线程,mainfun:自己要实现的功能的线程函数
HANDLE hThread=CreateThread(NULL,0,mainfun,NULL,0,NULL);
if(hThread==NULL)
return;
}
在ServiceMain中通过RegisterServiceCtrlHandler注册一个ServiceHandler函数用来处理程序对服
务的控制
3.ServiceHandler()
当你打开服务管理器,启动或停止一个服务的时候,对你的操作进行响应的就是ServiceHandler()函
数,它会判断你的操作然后做出响应,其实现代码如下:
VOID WINAPI ServiceHandler(DWORD fdwControl)
{
switch(fdwControl)
{
case SERVICE_CONTROL_PAUSE:
ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
SetServiceStatus(hStatus,&ServiceStatus);
return ;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
SetServiceStatus(hStatus,&ServiceStatus);//设置状态
return ;
}
二、安装和卸载服务实现:
以上是服务程序的实现,但是,上面的服务程序仅仅是一个服务而已,我们还没有启动这个服务,所
以下面我们来处理启动服务部分启动服务程序和服务程序可以结合在一起作为一个文件,也可以像下
面这样,另外写一个启动程序。
OpenSCManager: 用于打开服务控制管理器(servie control manager);
CreateService: 用于创建服务;
OpenService: 用于打开已有的服务,返回该服务的句柄;
ControlService: 则用于控制已打开的服务状态,这里是让服务停止后才删除;
DeleteService: 用于删除指定服务。
1、安装服务程序
#include <windows.h>
#include <winsvc.h>
#include <stdio.h>
main()
{
char name[100];
char info[200];
char path[300];
printf("请输入服务名/n/n");
scanf ("%s",&name);
printf("请输入服务描述/n/n");
scanf ("%s",&info);
printf("请输入程序路径/n/n");
scanf ("%s",&path);
SC_HANDLE manager=NULL;
SC_HANDLE service=NULL;
if((manager=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE))==NULL)
{
printf("OpenSCManager Error");
}
service=CreateService(
manager,name,info,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
path, 0, 0, 0, 0, 0 );
if(service)
printf("服务创建成功/n/n");
else
printf("服务创建失败/n/n");
CloseServiceHandle(service);
CloseServiceHandle(manager);
}
CreateService该函数用来创建服务,
第五个参数为SERVICE_WIN32_SHARE_PROCESS或者SERVICE_WIN32_OWN_PROCESS
如果仅仅创建一个服务的话,第五个参数用SERVICE_WIN32_SHARE_PROCESS
但是如果要创建多个服务的话:
例如,启动两个服务:
CreateService(……);
CreateService(……);
如果第五个参数为:
SERVICE_WIN32_OWN_PROCESS: 每个服务都有自己的一个独立进程
此时,打开任务管理器可以看到有两个ServiceTest.exe的进程,
SERVICE_WIN32_SHARE_PROCESS:表示多个服务共享一个进程
此时,打开任务管理器可以看到只有一个ServiceTest.exe的进程,同时可以看到比
SERVICE_WIN32_OWN_PROCESS方式的线程数多一个
2、删除服务程序
#include <windows.h>
#include <winsvc.h>
#include <stdio.h>
void main()
{
char name[100];
SC_HANDLE scm;
SC_HANDLE service;
SERVICE_STATUS status;
printf("请输入要删除的服务名/n/n");
scanf ("%s",&name);
if((scm=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE))==NULL)
{
printf("OpenSCManager Error/n");
}
service=OpenService(scm,name,SERVICE_ALL_ACCESS|DELETE);
if (!service)
{
printf("OpenService error!/n");
return;
}
BOOL isSuccess=QueryServiceStatus(service,&status);
if (!isSuccess)
{
printf("QueryServiceStatus error!/n");
return;
}
if ( status.dwCurrentState!=SERVICE_STOPPED )
{
isSuccess=ControlService(service,SERVICE_CONTROL_STOP,&status);
if (!isSuccess )
printf("Stop Service error!/n");
Sleep( 500 );
}
isSuccess=DeleteService(service);
if (!isSuccess)
printf("删除服务失败!/n");
else
printf("删除服务成功!/n");
CloseServiceHandle(service );
CloseServiceHandle(scm);
}
SERVICE_STATUS:该结构体的一些变量可自行查找资料了解,本文只是简单介绍服务程序实现。
备注:服务执行顺序为先启动服务,最好才运行服务程序本身,如果服务未调用CreateService启动,
就调用StartServiceCtrlDispatcher来启动服务的控制分派机线程
参考文章:
http://www.vckbase.com/document/listdoc.asp?mclsid=13&sclsid=1319
http://www.hongke-vip.com/read.php?tid-34125.html
附加测试程序源码(由http://www.vckbase.com/document/listdoc.asp?mclsid=13&sclsid=1319资源修改)
http://download.youkuaiyun.com/source/2495451