简单的C++代码编写windows服务

继上一章flex通信之后,接下来需要为程序集成到windows服务做准备了,首先需要学习如何编写一个windows服务。

一,windows服务的代码如下:

#include "stdafx.h"
#include "resource.h"

using namespace std;

//服务的状态,和服务停止事件
SERVICE_STATUS			serviceStatus;
SERVICE_STATUS_HANDLE	serviceStatusHandle;
HANDLE					serviceStopEvent;

//服务的控制
void WINAPI ServiceMain(DWORD, LPTSTR*);
void WINAPI ServiceInit(DWORD, LPTSTR*);
void WINAPI ServiceContrl(DWORD optionCode);

//记录服务的状态
void ReportServiceStatus(DWORD, DWORD, DWORD);

//服务的安装与卸载,服务的状态
BOOL Install();
BOOL Uninstall();

//属性与对象
TCHAR serviceName[256];
TCHAR serviceDisplayName[256];
TCHAR serviceMainClassPath[256];
TCHAR serviceDescription[256];

int _tmain(int argc, _TCHAR* argv[]) {
	outLog("main start");
	cout << "main start" << endl;
	TCHAR* actionArg = argv[1];

	//如果传入了参数"install",则安装服务,另外服务能够被SCM控制
	if (lstrcmpi(actionArg, _T("install")) == 0) {
		Install();
	}
	//输入的参数为卸载时
	else if (lstrcmpi(actionArg, _T("uninstall")) == 0) {
		Uninstall();
	}
	//服务的数组信息
	SERVICE_TABLE_ENTRY dispatchTable[] = {
		{ serviceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain }
	};

	//启动服务控制方法启动服务,判断启动失败时
	if (!StartServiceCtrlDispatcher(dispatchTable)) {
		outLog("StartServiceCtrlDispatcher error", GetLastError());
		//Uninstall();
		return -1;
	}
	else {
		outLog("StartServiceCtrlDispatcher successfully");
	}

	return 0;
}

/**
安装服务
**/
BOOL Install() {
	//控制器
	SC_HANDLE schSCManager;
	SC_HANDLE schService;
	TCHAR servicePath[MAX_PATH];
	//服务描述
	SERVICE_DESCRIPTION serviceDesc;


	//加载多语言字段
	LoadString(NULL, IDS_SERVICENAME, serviceName, sizeof(serviceName) / sizeof(TCHAR));
	LoadString(NULL, IDS_SERVICEDISPLAYNAME, serviceDisplayName, sizeof(serviceDisplayName) / sizeof(TCHAR));
	LoadString(NULL, IDS_SERVICEMAINCLIASSPATH, serviceMainClassPath, sizeof(serviceMainClassPath) / sizeof(TCHAR));
	LoadString(NULL, IDS_SERVICEDESCRIPTION, serviceDescription, sizeof(serviceDescription) / sizeof(TCHAR));


	//判断文件是否可访问
	if (!GetModuleFileName(NULL, servicePath, MAX_PATH)) {
		cout << "Cannot install service" << endl;
		return false;
	}

	//打开服务控制管理器
	schSCManager = OpenSCManager(
		NULL,							//本地电脑
		NULL,							//服务激活的位置
		SC_MANAGER_ALL_ACCESS);			//全部动作允许

	if (NULL == schSCManager) {
		cout << "OpenSCManager failed" << endl;
		return false;
	}

	//创建服务
	schService = CreateService(
		schSCManager,					//服务管理控制器对象
		serviceName,					//名称
		serviceDisplayName,				//显示的名称
		SERVICE_ALL_ACCESS,				//访问请求
		SERVICE_WIN32_OWN_PROCESS,		//服务类型
		SERVICE_AUTO_START,				//启动类型  自动 SERVICE_AUTO_START,手动 SERVICE_DEMAND_START,禁止 SERVICE_DISABLED
		SERVICE_ERROR_NORMAL,			//错误类型
		servicePath,					//服务路径
		NULL,							//不导入额外的组
		NULL,							//不标记权限
		NULL,							//不依赖
		NULL,							//本地账号
		NULL);							//无密码

	if (NULL == schService) {
		outLog("CreateService failed", GetLastError());
		CloseServiceHandle(schSCManager);
		return false;
	}
	else {
		outLog("Servcie install successfully");
	}

	//添加服务描述
	serviceDesc.lpDescription = serviceDescription;
	boolean changeRes = ChangeServiceConfig2(
		schService,							//服务控制器
		SERVICE_CONFIG_DESCRIPTION,			//改变:描述
		&serviceDesc);						//新的描述
	if (!changeRes) {
		outLog("ChangeServiceConfig2 DESCRIPTION failed");
	}
	else {
		outLog("ChangeServiceConfig2 DESCRIPTION successfully");
	}


	//启动服务,成功则关闭控制器
	boolean startServiceRes = StartService(schService, 0, NULL);
	if (!startServiceRes) {
		outLog("StartService failed", GetLastError());
		//关闭获得的控制器
		CloseServiceHandle(schService);
		CloseServiceHandle(schSCManager);
	}
	else {
		outLog("StartService successfully");
	}

	//关闭获得的控制器
	CloseServiceHandle(schService);
	CloseServiceHandle(schSCManager);
	return true;
}

/**
卸载服务
**/
BOOL Uninstall() {
	SC_HANDLE schSCManager;
	SC_HANDLE schService;

	//打开服务控制管理器
	schSCManager = OpenSCManager(
		NULL,							//本地电脑
		NULL,							//服务激活的位置
		SC_MANAGER_ALL_ACCESS);			//全部动作允许

	if (NULL == schSCManager) {
		outLog("Uninstall OpenSCManager failed");
		return false;
	}

	//打开服务
	schService = OpenService(
		schSCManager,					//服务管理控制器对象
		serviceName,					//名称
		SERVICE_STOP | DELETE);

	if (NULL == schService) {
		CloseServiceHandle(schSCManager);
		outLog("Uninstall OpenService failed");
		return false;
	}

	//停止服务
	ControlService(schService, SERVICE_CONTROL_STOP, &serviceStatus);

	//删除服务
	BOOL deleteServcie = DeleteService(schService);

	//关闭控制器
	CloseServiceHandle(schService);
	CloseServiceHandle(schSCManager);

	if (deleteServcie) {
		return true;
	}

	outLog("Service could not be deleted");
	return false;
}

/**
服务主方法,服务的主要逻辑
**/
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
	outLog("ServiceMain start");
	//给服务注册控制器
	serviceStatusHandle = RegisterServiceCtrlHandler(
		serviceName,
		ServiceContrl);

	//判断是否注册成功
	if (!serviceStatusHandle) {
		outLog("RegisterServiceCtrlHandler failed");
		return;
	}

	//重制服务的状态码 SERVICE_STATUS
	serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
	serviceStatus.dwServiceSpecificExitCode = 0;

	//记录服务状态到服务管理器上
	ReportServiceStatus(SERVICE_START_PENDING, NO_ERROR, 3000);

	//初始化
	ServiceInit(dwArgc, lpszArgv);
}

/**
初始化服务
dwArgc - 传入的数组长度
lpszArgv - 传入的数组
**/
void WINAPI ServiceInit(DWORD dwArgc, LPTSTR *lpszArgv) {
	//定义和初始化所需的参数,保证SERVICE_START_PENDING能够访问
	//ReportSvcStatus().如果初始化失败则改变服务状态为SERVICE_STOPPED.

	//创建一个事件,当接收到停止代码时触发动作
	serviceStopEvent = CreateEvent(
		NULL,										//默认的安全参数
		TRUE,										//手工重制Event
		FALSE,										//初始为无信号
		NULL);										//没有名称

	if (NULL == serviceStopEvent) {
		ReportServiceStatus(SERVICE_STOP, NO_ERROR, 0);
		return;
	}

	//初始化完后记录运行状态
	ReportServiceStatus(SERVICE_RUNNING, NO_ERROR, 0);

	//当服务停止时
	while (1) {
		//检查服务是否停止(即停止事件是否被触发)
		WaitForSingleObject(serviceStopEvent, INFINITE);
		ReportServiceStatus(SERVICE_STOPPED, NO_ERROR, 0);
		return;
	}
}
/**
设置当前服务状态并且记录到服务管理器中
**/
void ReportServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) {
	static DWORD dwCheckPoint = 1;

	//初始化SERVICE_STATUS结构体
	serviceStatus.dwCurrentState = dwCurrentState;			//当前状态	
	serviceStatus.dwWin32ExitCode = dwWin32ExitCode;		//错误码
	serviceStatus.dwWaitHint = dwWaitHint;				//等待时间ms

	//指定了控制请求是否通知服务,0为不通知
	if (dwCurrentState == SERVICE_START_PENDING) {
		serviceStatus.dwControlsAccepted = 0;
	}
	else {
		serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
	}

	//设置等待时间,dwWaitHint为超时时间,dwCheckPoint报告服务状态的改变次数
	if ((dwCurrentState == SERVICE_RUNNING) ||
		(dwCurrentState == SERVICE_STOPPED)) {
		serviceStatus.dwCheckPoint = 0;
	}
	else {
		serviceStatus.dwCheckPoint = dwCheckPoint++;
	}

	//记录服务的状态到任务资源管理器
	SetServiceStatus(serviceStatusHandle, &serviceStatus);
}

/**
访问服务管理器改变服务的状态时会访问此方法
**/
void WINAPI ServiceContrl(DWORD dwCtrl) {
	outLog("ServiceContrl:", dwCtrl);
	//请求的控制代码
	switch (dwCtrl) {
	case SERVICE_CONTROL_STOP://停止服务
		ReportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
		//发送服务停止信号
		SetEvent(serviceStopEvent);
		ReportServiceStatus(serviceStatus.dwCurrentState, NO_ERROR, 0);
		break;
	case SERVICE_CONTROL_INTERROGATE://询问
		break;
	case SERVICE_CONTROL_PAUSE:
		break;
	case SERVICE_CONTROL_CONTINUE:
		break;
	case SERVICE_CONTROL_SHUTDOWN:
		break;
	default:
		outLog("error ServiceContrl code", dwCtrl);
		break;
	}
}
window服务需要展示一些服务的信息,为了改动方便,引入资源文件:LoadJVMDemo.rc

二,资源文件包含一个String Table资源和Version资源


String Table资源内容为:


对应的生成的resource.h文件内容为:

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 LoadJVMDemo.rc 使用
//
#define IDS_SERVICENAME                 101
#define IDS_SERVICEDISPLAYNAME          102
#define IDS_SERVICEMAINCLIASSPATH       103
#define IDS_SERVICEDESCRIPTION          104

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif
在cmd中安装


在系统服务中可以看到安装成功


在系统盘路径:C:\Windows\System32\LoadJVMDemoC.log下可以看到日志


在系统服务中将服务状态改成“停止”,然后再改成“启动”,可以看到日志如下


若以上日志正常打印,说明服务已经成功安装,并正常运行了。

三,删除服务

先停止服务,用管理员方式打开cmd,输入:sc stop ServiceDemo


接着输入:sc delete ServiceDemo


在系统服务中刷新可以看到之前的服务已经被删除了。



以上为简单的C++代码编写windows服务学习。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值