创建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写入数据,服务运行期间每隔两秒写入当前时间. 原理这些就不说了,三语两语说不清楚,直接贴一个实例 ...
随机推荐
- 使用Stack堆栈集合大数据运算
使用Stack堆栈集合大数据运算 package com.sta.to; import java.util.Iterator; import java.util.Stack; public class ...
- Ambari安装之部署单节点集群
前期博客 大数据领域两大最主流集群管理工具Ambari和Cloudera Manger Ambari架构原理 Ambari安装之Ambari安装前准备(CentOS6.5)(一) Ambari安装之部 ...
- Linux常用命令及shell技巧
这里列出一些个人在工作中常使用的各种linux命令,每一个不详细讲参数,只写经常用的参数.希望快速获得在linux命令行工作的能力的朋友可以看看.本人一直觉的,不使用linux 图形界面,以xshel ...
- 树上差分 (瞎bb) [树上差分][LCA]
做noip2015的运输计划写了好久好久写不出来 QwQ 于是先来瞎bb一下树上差分 混积分 树上差分有2个常用的功能: (1)记录从点i到i的父亲这条路径走过几次 (2)将每条路径(s,t ...
- SSH三大框架的各自工作流程
一.Struts2的工作流程:1.用户在客户端发起请求,客户端会初始化一个servlet容器请求:2.servlet容器把请求会传递给context容器,context容器找到目标web工程.3.进行 ...
- (转)硬盘分区备忘(主分区,扩展分区和逻辑分区)以及Linux硬盘分区工具parted 介绍
场景:最近在学习Linux的基础知识,不可避免的设计到Linux的磁盘分区,以前做过总结,但是那种总结就是复制别人的文章,总结完就不想看第二遍,所以很容易就遗忘了!清楚明白的理解分区后,我就可以在自己 ...
- 线上故障排查——drools规则引擎使用不当导致oom
事件回溯 1.7月26日上午11:34,告警邮件提示:tomcat内存使用率连续多次超过90%: 2.开发人员介入排查问题,11:40定位到存在oom问题,申请运维拉取线上tomcat 内存快照dum ...
- 【JQUERY】插件的写法
1. jquery插件怎么写 $.extend $.fn 2. 写的时候注意些什么
- EasyUi+Spring Data 实现按条件分页查询
Spring data 介绍 Spring data 出现目的 为了简化.统一 持久层 各种实现技术 API ,所以 spring data 提供一套标准 API 和 不同持久层整合技术实现 . 自己 ...
- 【ES】ElasticSearch初体验之使用Java进行最基本的增删改查~
好久没写博文了, 最近项目中使用到了ElaticSearch相关的一些内容, 刚好自己也来做个总结. 现在自己也只能算得上入门, 总结下自己在工作中使用Java操作ES的一些小经验吧. 本文总共分为三 ...