创建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写入数据,服务运行期间每隔两秒写入当前时间. 原理这些就不说了,三语两语说不清楚,直接贴一个实例 ...
随机推荐
- 浅谈身为小白学习Linux系统的四点实用建议
游戏.办公.安全,可以总结为是方便当代人们在生活中的刚需,我们大都是这些服务的使用者,而把单个功能整合起来那就必须谈到互联网,自然而然通过互联网要将Service发送给Service manageme ...
- 51nod_1417:天堂里的游戏
题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1417 假设 ans=n/m,C=(A+B)/2 若出正面 ...
- 2017年1月1日 App Store中的所有应用都必须启用 App Transport Security安全功能
2017年1月1日 App Store中的所有应用都必须启用 App Transport Security安全功能,否则极有可能被拒! 在WWDC 2016开发者大会上,苹果宣布了一个最后期限:到20 ...
- 扩展entity framework core 实现默认字符串长度,decimal精度,entity自动注册和配置
报道越短,事情越严重!文章越短,内容越精悍! 文章以efcore 2.0.0-preview2.测试验证通过.其他版本不保证使用,但是思路不会差太远.源代码 目标: 1.实现entity的自动发现和m ...
- 初次配置git与github出现push不了的问题
ssh: connect to host gmail.com port 22: No route to host fatal: Could not read from remote repositor ...
- 在同一个sql语句中,统计不同条件的Count数量
前几天帮同事优化了个SQL,原写法使用多个子查询这里不再重现了,大家都遇到过这样一种情况,在项目后期的维护中, 修改别人的SQL代码,超过30行的语句,多层子查询,读起来很坑,时间久的项目伴随着人员的 ...
- HDU--1195--bfs--Open the Lock
/* Name: HDU--1195--Open the Lock Author: shen_渊 Date: 17/04/17 08:54 Description: bfs,用四维数组标记状态,每位数 ...
- 【python密码学编程】7.暴力破解凯撒加密法
# _*_ coding:utf-8 _*_ #Caeser Ciper import pyperclip messgae = 'GUVF VF ZL FRPERG ZRFFTNR.' nums = ...
- Linux下SVN配置
1.安装svnyum install subversion 2.创建版本库fengyu(版本库的名字取来和你web项目的名字相同,否则你在服务器检出后会变成web项目里还有一层版本库的目录,里面才是项 ...
- HTML <div>和<span>
块代码 <div>和<span> 1.. <style> .ccwTest { font-family: '.PingFang SC';">; co ...