创建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写入数据,服务运行期间每隔两秒写入当前时间. 原理这些就不说了,三语两语说不清楚,直接贴一个实例 ...
随机推荐
- 列表的系列操作(python)
除了定义和切片外,这里总结下系列的操作: # hanbb come on! names = ["hbb",'tian','bao','cheng'] #Add names.appe ...
- JavaWeb开发技术基础概念回顾篇
JavaWeb开发技术基础概念回顾篇 第一章 动态网页开发技术概述 1.JSP技术:JSP是Java Server Page的缩写,指的是基于Java服务器端动态网页. 2.JSP的运行原理:当用户第 ...
- mysql浅龟定
一,尽量不字啊数据库做运算 1,尽量不再数据库做运算, 2,将复杂运算移动到cpu 3,尽可能简单应用mysql 二,控制表数据量 1,纯 int不超过1000w 2,含char不超过500w 3,建 ...
- Css元素居中设置
你对DIV CSS居中的方法是否了解,这里和大家分享一下,用CSS让元素居中显示并不是件很简单的事情,让我们先来看一下CSS中常见的几种让元素水平居中显示的方法. DIV CSS居中 用CSS让元素居 ...
- 数据结构基础:栈(Stack)
什么是栈? 栈是限制插入和删除只能在同一个位置上进行的表,这个位置就是栈的顶端,对于栈的操作主要有三种形式:入栈(将元素插入到表中),出栈(将表最后的元素删除,也就是栈顶的元素),返回栈顶元素 ...
- python3网络编程之socketserver
本节主要是讲解python3网络编程之socketserver,在上一节中我们讲到了socket.由于socket无法支持多用户和多并发,于是就有了socket server. socket serv ...
- tomcat 与 java web中url路径的配置以及使用规则详情(长期更新)
首先我们看一下在myeclipse中建立的java web项目的结构 在这里我们需要注意这个webroot也就是我们在tomcat里的webapp里面的应用 之所以每一个项目都有这个webroot,是 ...
- [补档][ZJOI2007] 报表统计
[ZJOI2007] 报表统计 题目 传送门 小Q的妈妈是一个出纳,经常需要做一些统计报表的工作.今天是妈妈的生日,小Q希望可以帮妈妈分担一些工作,作为她的生日礼物之一. 经过仔细观察,小Q发现统计一 ...
- Base:一种 Acid 的替代方案
原文链接: BASE: An Acid Alternative 数据库 ACID,都不陌生:原子性.一致性.隔离性和持久性,这在单台服务器就能搞定的时代,很容易实现,但是到了现在,面对如此庞大的访问量 ...
- echarts 支持svg格式
今天研究了下echarts的svg格式.发现用ai生成svg格式的图片,echarts上面显示不了. 经过了多次的百度和谷歌终于找到了用Method Draw画出来的svg格式,echarts就能加载 ...