创建Windows服务(C++)
这次我们来创建一个windows本地服务,需要有以下功能:
- 安装服务。
- 卸载服务。
- 手动启动服务。
- 开机自动启动服务。
- 控制服务(停止、暂停、恢复、启动)。
服务概念及介绍
看下图,一切尽在不言中了(-_-):

安装服务并开机启动
代码逻辑: 打开SCM(Service Control Manager)-> 创建服务。
在CreateService调用中,我们传入
SERVICE_AUTO_START里表明这个服务是开启自启动的,SCM会在开机时调用StartService来启动我们的服务;同时我们传入NULL作为服务开始名称,这样该服务就可以开机启动为系统服务。在调用installService后,我们会调用startService来手动启动服务。这里我用
SAFE_CALL简化了错误处理逻辑。wstring getExeFullFilename()
{
static wchar_t buffer[1024]; SAFE_CALL(GetModuleFileNameW(NULL, buffer, 1024), 0);
return wstring(buffer);
} void installService()
{
auto scmHandle = OpenSCManagerW(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
SAFE_CALL(scmHandle, NULL); auto serviceHandle = CreateServiceW(scmHandle,
L"lgxZJ::Service",
L"lgxZJ::Service",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
getExeFullFilename().c_str(),
NULL, NULL, L"", NULL, L"");
SAFE_CALL(serviceHandle, NULL); CloseServiceHandle(scmHandle);
CloseServiceHandle(serviceHandle);
} void startService()
{
auto scmHandle = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SAFE_CALL(scmHandle, NULL); auto serviceHandle = OpenServiceW( scmHandle,
L"lgxZJ::Service",
SERVICE_ALL_ACCESS);
SAFE_CALL(serviceHandle, NULL); SERVICE_STATUS serviceStatus;
SAFE_CALL(QueryServiceStatus(serviceHandle, &serviceStatus), 0);
if (serviceStatus.dwCurrentState == SERVICE_START &&
serviceStatus.dwCurrentState != SERVICE_START_PENDING)
return; SAFE_CALL(StartServiceW(serviceHandle, 0, NULL), FALSE); CloseServiceHandle(scmHandle);
CloseServiceHandle(serviceHandle);
} #define SAFE_CALL(FuncCall, ErrorCode) \
if (FuncCall == ErrorCode) { \
cout << #FuncCall " error, code:" << GetLastError() \
<< " ,line:" << \__LINE__ << "\n"; \
exit(-1); \
}
卸载服务
代码逻辑: 打开SCM(Service Control Manager)-> 打开服务 -> 停止服务(如果正在运行) -> 删除服务。
void uninstallService()
{
auto scmHandle = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SAFE_CALL(scmHandle, NULL); auto serviceHandle = OpenServiceW( scmHandle,
L"lgxZJ::Service",
SERVICE_ALL_ACCESS);
SAFE_CALL(serviceHandle, NULL); SERVICE_STATUS serviceStatus;
SAFE_CALL(QueryServiceStatus(serviceHandle, &serviceStatus), 0);
if (serviceStatus.dwCurrentState == SERVICE_RUNNING) {
SAFE_CALL(ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus), 0);
SAFE_CALL(serviceStatus.dwCurrentState, NO_ERROR); do {
SAFE_CALL(QueryServiceStatus(serviceHandle, &serviceStatus), 0);
Sleep(1000);
} while (serviceStatus.dwCurrentState != SERVICE_STOPPED);
} SAFE_CALL(DeleteService(serviceHandle), FALSE); CloseServiceHandle(scmHandle);
CloseServiceHandle(serviceHandle);
}
手动启动服务
代码逻辑: 打开SCM -> 打开服务 -> 启动服务。
void startService()
{
auto scmHandle = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SAFE_CALL(scmHandle, NULL); auto serviceHandle = OpenServiceW( scmHandle,
L"lgxZJ::Service",
SERVICE_ALL_ACCESS);
SAFE_CALL(serviceHandle, NULL); SERVICE_STATUS serviceStatus;
SAFE_CALL(QueryServiceStatus(serviceHandle, &serviceStatus), 0);
if (serviceStatus.dwCurrentState == SERVICE_START &&
serviceStatus.dwCurrentState != SERVICE_START_PENDING)
return; SAFE_CALL(StartServiceW(serviceHandle, 0, NULL), FALSE); CloseServiceHandle(scmHandle);
CloseServiceHandle(serviceHandle);
}
运行服务(服务启动时会运行服务)、服务控制处理
代码逻辑: 启动分发器(连接到SCM) -> 注册服务控制处理器 -> 在控制处理器中对服务控制进行处理(通过SetServiceStatus反馈服务状态和设置接受的控制)。
void runService()
{
const SERVICE_TABLE_ENTRYW serviceTable[] = {
{ L"", ServiceMain },
{ NULL, NULL }
}; SAFE_CALL(StartServiceCtrlDispatcherW(&serviceTable[0]), 0);
} SERVICE_STATUS_HANDLE g_serviceStatusHandle = NULL; void setServiceStatus(DWORD status)
{
SERVICE_STATUS serviceStatus;
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwWin32ExitCode = NO_ERROR;
serviceStatus.dwServiceSpecificExitCode = 0;
serviceStatus.dwWaitHint = 2000;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_PAUSE_CONTINUE |
SERVICE_ACCEPT_SHUTDOWN |
SERVICE_ACCEPT_STOP; serviceStatus.dwCurrentState = status;
SAFE_CALL(SetServiceStatus(g_serviceStatusHandle, &serviceStatus), 0);
} VOID WINAPI ServiceHandler(DWORD controlCode)
{
switch (controlCode)
{
case SERVICE_CONTROL_CONTINUE:
setServiceStatus(SERVICE_START_PENDING); break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_PAUSE:
setServiceStatus(SERVICE_PAUSED); break;
case SERVICE_CONTROL_SHUTDOWN:
setServiceStatus(SERVICE_STOPPED); break;
case SERVICE_CONTROL_STOP:
setServiceStatus(SERVICE_STOPPED); break;
default:
break;
}
} VOID WINAPI ServiceMain(DWORD argc, LPWSTR *argv)
{
g_serviceStatusHandle = RegisterServiceCtrlHandlerW(L"lgxZJ::Service", &ServiceHandler);
if (g_serviceStatusHandle == 0)
{
cout << "RegisterServiceCtrlHandlerW error, code:" << GetLastError()
<< " ,line:" << __LINE__ << "\n";
exit(-1);
} setServiceStatus(SERVICE_START_PENDING);
setServiceStatus(SERVICE_RUNNING);
}
完整代码
生成的exe需要以管理员权限启动,完整代码见此处。
创建Windows服务(C++)的更多相关文章
- 用C#创建Windows服务(Windows Services)
用C#创建Windows服务(Windows Services) 学习: 第一步:创建服务框架 创建一个新的 Windows 服务项目,可以从Visual C# 工程中选取 Windows 服务(W ...
- 玩转Windows服务系列——创建Windows服务
创建Windows服务的项目 新建项目->C++语言->ATL->ATL项目->服务(EXE) 这样就创建了一个Windows服务项目. 生成的解决方案包含两个项目:Servi ...
- .Net创建windows服务入门
本文主要记录学习.net 如何创建windows服务. 1.创建一个Windows服务程序 2.新建安装程序 3.修改service文件 代码如下 protected override void On ...
- C# 创建Windows服务
创建windows服务项目 2 右键点击Service1.cs,查看代码, 用于编写操作逻辑代码 3 代码中OnStart用于执行服务事件,一般采用线程方式执行方法,便于隔一段事件执行一回 END ...
- 使用Topshelf创建Windows服务
概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的 ...
- [转]C#创建Windows服务与安装
本文档用于创建windows服务说明,使用vs2010系统平台 创建项目 1 创建windows服务项目 2 右键点击Service1.cs,查看代码, 用于编写操作逻辑代码 3 代码中OnStart ...
- [Solution] Microsoft Windows 服务(2) 使用Topshelf创建Windows服务
除了通过.net提供的windows服务模板外,Topshelf是创建Windows服务的另一种方法. 官网教程:http://docs.topshelf-project.com/en/latest/ ...
- 在64位windows下使用instsrv.exe和srvany.exe创建windows服务
在64位windows下使用instsrv.exe和srvany.exe创建windows服务 在32位的windows下,包括windows7,windows xp以及windows 2003, ...
- 使用Topshelf 5步创建Windows 服务 z
使用Topshelf创建Windows 服务简要的介绍了创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with T ...
- C#创建windows服务搭配定时器Timer使用实例(用代码做,截图版)
功能说明:C#创建一个windows服务,服务启动时D:\mcWindowsService.txt写入数据,服务运行期间每隔两秒写入当前时间. 原理这些就不说了,三语两语说不清楚,直接贴一个实例 ...
随机推荐
- Luogu 1111 修复公路(最小生成树)
Luogu 1111 修复公路(最小生成树) Description A地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 给出A地区的村庄数N,和公路数M,公路是双向的 ...
- springJdbc like模糊查询,Spring namedParameterJdbcTemplate like查询
springJdbc like模糊查询,Spring namedParameterJdbcTemplate like查询, SpringJdbc命名参数like模糊查询,namedParameterJ ...
- Java之异常处理,日期处理
Java异常处理 异常:异常就是Java程序在运行过程中出现的错误. 异常由来:问题也是现实生活中一个具体事务,也可以通过java 的类的形式进行描述,并封装成对象.其实就是Java对不正常情况进行描 ...
- MSDTC启用——分布式事务
一.前言 最近在做一个项目的时候使用了.NET中的System.Transactions(分布式事务),当项目开发完成以后,调用的时候遇到了MSDTC的问题,在查阅了相关资料后将这个问题解决了,大致的 ...
- HDU 6035---Colorful Tree(树形DP)
题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...
- ubuntu解压乱码
乱码原因 问题一般出现在windows下压缩的在ubuntu中会出现这种情况. 其实就是windows和ubuntu下压缩的编码格式不同.windows下的编码格式为GBK,Ubuntu下的为UTF- ...
- 练习半音阶口琴--->>修理推键所感
我想,自己现在已经是完全迷上口琴了,在最近练习的时候自己发现推键推到最后的时候,推不过去了,以为是摩擦的问题,于是刻了轨道来减少摩擦,但是效果并不是很明显,于是,自己开始起了买新口琴的心,想换个好一点 ...
- vue-项目入门
初入前端的新人在碰到vue.js后,去过官网,估计粗略的看下api文档以后会以为vue的安装只是把那串js代码直接粘贴复制到文档即可,虽然这样是可以,但那在项目中并不合适. 项目中的vue引入(配制安 ...
- 暑假集训D11总结
%dalao 今天某学长来讲一个极其高深的数据结构——线段树(woc哪里高深了),然而并没有时间整理笔记= =,所以明天在扔笔记咯= = 考试 今天考试,一看数据范围,woc暴力分给的真足,然后高高兴 ...
- idea如何添加外部jar包
假设我们要将G:\ModuleAPI_Java_2.2.0.0 .jar导入工程中: 首先,在mvn命令行执行下面命令: mvn install:install-file -Dfile=G:\Modu ...