本文主要介绍基于控制台的服务程序控制程序的编写,主要完成创建、启动、停止、卸载等功能,读者可自行添加功能。

首先来介绍需要用到的几个主要的函数。


1.   SC_HANDLE  OpenSCManager(   LPCTSTR  lpMachineName,   LPCTSTR   lpDatabaseName,   DWORD  dwDesiredAccess)  

OpenSCManager   函数打开指定计算机上的service control manager   database(WINNT通过一个名为service   control  manager   database的数据库来管理所有的Service,因此对Service的任何操作都应打开此数据库。)。

其中参数lpMachineName指定计算机名,若为空则指定为本机。

LpDatabaseName为指定要打开的service   control  manager   database名,   默认为空。

dwDesiredAccess指定操作的权限,   可以为下面取值之一:  

SC_MANAGER_ALL_ACCESS   //所有权限  

SC_MANAGER_CONNECT   //允许连接到service  control  manager   database  

SC_MANAGER_CREATE_SERVICE   //允许创建服务对象并把它加入database  

SC_MANAGER_ENUMERATE_SERVICE   //允许枚举database   中的Service  

SC_MANAGER_LOCK   //允许锁住database  

SC_MANAGER_QUERY_LOCK_STATUS   //允许查询database的封锁信息  


如果函数成功,返回值是一个句柄指定的服务控制管理器数据库。如果函数失败,返回值为NULL 。要获得扩展错误信息,请使用GetLastError 获得错误代码。

例:   SC_HANDLE	sc = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);



2.SC_HANDLE   CreateService(SC_HANDLE  hSCManager,  LPCTSTR  lpServiceName, LPCTSTR  lpDisplayName,   

DWORD  dwDesiredAccess,  DWORD  dwServiceType,   DWORD  dwStartType,  DWORD  dwErrorControl,  

         LPCTSTR   lpBinaryPathName,  

         LPCTSTR   lpLoadOrderGroup,  

         LPDWORD   lpdwTagId,  

         LPCTSTR   lpDependencies,  

         LPCTSTR   lpServiceStartName,  

         LPCTSTR   lpPassword)

CreatService函数产生一个新的SERVICE。其中参数hSCManager为指向service   control   manager  database   的句柄,由OpenSCManager返回。LpServiceName为SERVICE的名字,lpDisplayName为Service显示用名,dwDesiredAccess是访问权限,本程序中用SERVICE_ALL_ACCESS。wServiceType,指明SERVICE类型,本程序中用SERVICE_WIN32_OWN_PROCESS|   SERVICE_INTERACTIVE_PROCESS。dwStartType为Service启动方式,本程序采用自启动,即dwStartType等于SERVICE_AUTO_START。   dwErrorControl说明当Service在启动中出错时采取什么动作,本程序采用SERVICE_ERROR_IGNORE即忽约错误,读者可以改为其他的。LpBinaryPathName指明Service本体程序的路径名。剩下的五个参数一般可设为NULL。如函数调用成功则返回这个新Service的句柄,失败则返回NULL。与此函数对应的是DeleteService(   hService),它删除指定的Service。

例: CreateService(sc,TEXT(SERVICENAME),TEXT(SERVICENAME),SERVICE_ALL_ACCESS,
           SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,SERVICE_AUTO_START,
           SERVICE_ERROR_IGNORE,TEXT(SERVICEPATH),NULL,NULL,NULL,NULL,NULL )



3.  SC_HANDLE   OpenService(SC_HANDLE  hSCManager,LPCTSTR  lpServiceName,   DWORD   dwDesiredAccess   )  

函数调用成功则返回打开的Service句柄,失败则返回NULL。

例:OpenService(sc,TEXT(SERVICENAME),SERVICE_ALL_ACCESS);



4.  BOOL  

StartService(  SC_HANDLE   hService,   DWORD  dwNumServiceArgs,LPCTSTR   *lpServiceArgVectors   )  

StartService函数启动指定的Service。其中参数hService   为指向Service的句柄,由OpenService返回。dwNumServiceAr为启动服务所需的参数的个数。lpszServiceArgs  为启动服务所需的参数。若服务没有参数可分别设为0和NULL。

函数执行成功则返回True,   失败则返回False。

例:StartService(service,0,NULL)



5.BOOL  

ControlService(SC_HANDLE   hService  DWORD   dwControl,LPSERVICE_STATUS   lpServiceStatus )

Service程序没有专门的停止函数,而是用ControlService函数来控制Service的暂停、继续、停止等操作。参数dwControl指定发出的控制命令,可以为以下几个值:  

 SERVICE_CONTROL_STOP //停止Service

 SERVICE_CONTROL_PAUSE //暂停Service

 SERVICE_CONTROL_CONTINUE //继续Service

 SERVICE_CONTROL_INTERROGATE //查询Service的状态

 SERVICE_CONTROL_SHUTDOWN     //让ControlService调用失效

参数lpServiceStatus是一个指向SERVICE_STATUS的指针。SERVICE_STATUS是一个比较重要的结构,它包含了Service的各种信息,如当前状态、可接受何种控制命令等等。


函数执行成功则返回True,   失败则返回False。

例:SERVICE_STATUS ServiceStatus;
    ControlService(service, SERVICE_CONTROL_STOP,&ServiceStatus)



6.BOOL  

QueryServiceStatus(   SC_HANDLE  hService,LPSERVICE_STATUS  lpServiceStatus   )  

QueryServiceStatus函数比较简单,它查询并返回当前Service的状态。  

例:  QueryServiceStatus(service,&ServiceStatus); 
      if(ServiceStatus.dwCurrentState== SERVICE_RUNNING)   //正在运行
      {
          //do something
      }
      if(ServiceStatus.dwCurrentState==SERVICE_STOPPED )   //停止
      {
         //do something
      }




编制一个Service一般需要两个程序,一个是Service本体,一个是用于对Service进行控制的控制程序。 对于Service本体程序的编写本文不再介绍,上一篇文章有详细介绍。下面看看控制程序的完整源代码。


#include <stdio.h>
#include <windows.h>

#define SERVICENAME	"UDPserver"
#define	SERVICEPATH	"C:\\UDPservice\\UDPservice.exe"

void menu();

int main()
{
	SC_HANDLE	sc,service;
	sc = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
	SERVICE_STATUS ServiceStatus; 
	
	int num = 1;
	

	while(num)
	{
		menu();
		scanf("%d",&num);
		switch (num)
		{
		case 1:
			{
			if(CreateService(sc,TEXT(SERVICENAME),TEXT(SERVICENAME),
SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS| SERVICE_INTERACTIVE_PROCESS,
			SERVICE_AUTO_START,SERVICE_ERROR_IGNORE,TEXT(SERVICEPATH),
                        NULL,NULL,NULL,NULL,NULL )== NULL)
			{
				CloseServiceHandle(sc);
				printf("创建失败!\n");
				return -1;
			}
			else
			{
				printf("创建成功!\n");
			}
			break;
			}
		case 2:
			{
				service = OpenService(sc,TEXT(SERVICENAME),SERVICE_ALL_ACCESS);
				if( service == NULL)
				{
					printf("%d",GetLastError());
					CloseServiceHandle(sc);
					printf("打开失败!\n");
					return -1;
				}
				else
				{
					if(StartService(service,0,NULL))
					{
						printf("启动成功!\n");
					}
					else
					{
						printf("启动失败!\n");
						CloseServiceHandle(service);
						CloseServiceHandle(sc);
						return -1;
					}
				}
				break;
			}
		case 3:
			{
				if(ControlService(service, SERVICE_CONTROL_STOP,&ServiceStatus))
				{
					printf("停止成功!\n");
				}
				else
				{
					printf("停止失败!\n");
					CloseServiceHandle(sc);
					return -1;
				}
				break;
			}
		case 4:
			{
				if(DeleteService(service))
				{
					printf("卸载成功!\n");
				}
				else
				{
					printf("卸载失败!\n");
					CloseServiceHandle(sc);
					return -1;
				}
				break;
			}
		default:
			{
				printf("请输入 0-5 之间的数字!\n");
				break;
			}
		}
	}
	
	CloseServiceHandle(sc);

	
	return 0;

}

void menu()
{
	printf("*************欢迎使用UDPservice Control************\n");
	printf("请选择要执行的功能:\n");
	printf("1.创建UDPservice \n");
	printf("2.启动UDPservice \n");
	printf("3.停止UDPservice \n");
	printf("4.卸载UDPservice \n");
	printf("0.退出程序 \n");
	printf("请选择:");
}