这次我们来创建一个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++)的更多相关文章

  1. 用C#创建Windows服务(Windows Services)

    用C#创建Windows服务(Windows Services) 学习:  第一步:创建服务框架 创建一个新的 Windows 服务项目,可以从Visual C# 工程中选取 Windows 服务(W ...

  2. 玩转Windows服务系列——创建Windows服务

    创建Windows服务的项目 新建项目->C++语言->ATL->ATL项目->服务(EXE) 这样就创建了一个Windows服务项目. 生成的解决方案包含两个项目:Servi ...

  3. .Net创建windows服务入门

    本文主要记录学习.net 如何创建windows服务. 1.创建一个Windows服务程序 2.新建安装程序 3.修改service文件 代码如下 protected override void On ...

  4. C# 创建Windows服务

    创建windows服务项目   2 右键点击Service1.cs,查看代码, 用于编写操作逻辑代码 3 代码中OnStart用于执行服务事件,一般采用线程方式执行方法,便于隔一段事件执行一回 END ...

  5. 使用Topshelf创建Windows服务

    概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的 ...

  6. [转]C#创建Windows服务与安装

    本文档用于创建windows服务说明,使用vs2010系统平台 创建项目 1 创建windows服务项目 2 右键点击Service1.cs,查看代码, 用于编写操作逻辑代码 3 代码中OnStart ...

  7. [Solution] Microsoft Windows 服务(2) 使用Topshelf创建Windows服务

    除了通过.net提供的windows服务模板外,Topshelf是创建Windows服务的另一种方法. 官网教程:http://docs.topshelf-project.com/en/latest/ ...

  8. 在64位windows下使用instsrv.exe和srvany.exe创建windows服务

    在64位windows下使用instsrv.exe和srvany.exe创建windows服务   在32位的windows下,包括windows7,windows xp以及windows 2003, ...

  9. 使用Topshelf 5步创建Windows 服务 z

    使用Topshelf创建Windows 服务简要的介绍了创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with T ...

  10. C#创建windows服务搭配定时器Timer使用实例(用代码做,截图版)

       功能说明:C#创建一个windows服务,服务启动时D:\mcWindowsService.txt写入数据,服务运行期间每隔两秒写入当前时间. 原理这些就不说了,三语两语说不清楚,直接贴一个实例 ...

随机推荐

  1. 浅谈身为小白学习Linux系统的四点实用建议

    游戏.办公.安全,可以总结为是方便当代人们在生活中的刚需,我们大都是这些服务的使用者,而把单个功能整合起来那就必须谈到互联网,自然而然通过互联网要将Service发送给Service manageme ...

  2. 51nod_1417:天堂里的游戏

    题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1417 假设 ans=n/m,C=(A+B)/2 若出正面 ...

  3. 2017年1月1日 App Store中的所有应用都必须启用 App Transport Security安全功能

    2017年1月1日 App Store中的所有应用都必须启用 App Transport Security安全功能,否则极有可能被拒! 在WWDC 2016开发者大会上,苹果宣布了一个最后期限:到20 ...

  4. 扩展entity framework core 实现默认字符串长度,decimal精度,entity自动注册和配置

    报道越短,事情越严重!文章越短,内容越精悍! 文章以efcore 2.0.0-preview2.测试验证通过.其他版本不保证使用,但是思路不会差太远.源代码 目标: 1.实现entity的自动发现和m ...

  5. 初次配置git与github出现push不了的问题

    ssh: connect to host gmail.com port 22: No route to host fatal: Could not read from remote repositor ...

  6. 在同一个sql语句中,统计不同条件的Count数量

    前几天帮同事优化了个SQL,原写法使用多个子查询这里不再重现了,大家都遇到过这样一种情况,在项目后期的维护中, 修改别人的SQL代码,超过30行的语句,多层子查询,读起来很坑,时间久的项目伴随着人员的 ...

  7. HDU--1195--bfs--Open the Lock

    /* Name: HDU--1195--Open the Lock Author: shen_渊 Date: 17/04/17 08:54 Description: bfs,用四维数组标记状态,每位数 ...

  8. 【python密码学编程】7.暴力破解凯撒加密法

    # _*_ coding:utf-8 _*_ #Caeser Ciper import pyperclip messgae = 'GUVF VF ZL FRPERG ZRFFTNR.' nums = ...

  9. Linux下SVN配置

    1.安装svnyum install subversion 2.创建版本库fengyu(版本库的名字取来和你web项目的名字相同,否则你在服务器检出后会变成web项目里还有一层版本库的目录,里面才是项 ...

  10. HTML <div>和<span>

    块代码 <div>和<span> 1.. <style> .ccwTest { font-family: '.PingFang SC';">; co ...