C++程序服务化封装

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u011261430/article/details/76528993

之前有一篇“C++exe做系统服务,自动加载”是C语言风格的方式,使用是没有问题,但是很杂乱,这里对之封装,简化使用方式。

WindowsService.h

#pragma once
#include <string>
using namespace std;

//注入Windows服务类
class CWindowsService
{
public:
    CWindowsService();//构造函数
    CWindowsService(const string strServiceName);//构造函数
    ~CWindowsService();//析构函数

    void SetServiceName(const string strServiceName);//设置服务名称(所有操作前必须调用)

    void Run();//一键自助安装服务   

private:
    bool Install(int & dwCurrentState);//安装服务
    bool Uninstall();//卸载服务
    bool Start();//启动服务
    bool Stop();//停止服务

    static void ServiceMain(DWORD argc, LPTSTR *argv);//创建服务主要处理逻辑
    static void ServiceCtrlHandler(DWORD nControlCode);//接受servicecontrol 命令
    BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint);//更新服务状态 更新失败即结束服务
    BOOL StartServiceThread();//创建主窗口线程
    static DWORD ServiceExecutionThread(LPDWORD param);//创建服务主线程
    void KillService();// 停止服务 即结束主窗口线程 设置状态失败或是收到STOP SERVICE 命令调用此函数


private:
    HANDLE m_hServiceThread;
    SERVICE_STATUS_HANDLE m_nServiceStatusHandle;
    HANDLE m_EventkillService;
    HWND m_hMain;
    BOOL m_bServiceRunning;
    DWORD m_dwServiceCurrentStatus;

    string m_ServiceDisplayName;
    string m_ServiceName;
};

extern CWindowsService *g_pWindowsService;

WindowsService.cpp

#include "stdafx.h"
#include "WindowsService.h"
#include "server.h"

CWindowsService *g_pWindowsService = NULL;

//构造函数
CWindowsService::CWindowsService()
{
    m_hServiceThread = 0;
    m_nServiceStatusHandle = 0;
    m_EventkillService = NULL;
    m_hMain = NULL;
    m_bServiceRunning = FALSE;
    m_dwServiceCurrentStatus = 0;
}

CWindowsService::CWindowsService(const string strServiceName)
{
    CWindowsService();
    m_ServiceDisplayName = strServiceName;
    m_ServiceName = strServiceName;
}

//析构函数
CWindowsService::~CWindowsService()
{
}

//设置服务名称
void CWindowsService::SetServiceName(const string strServiceName)
{
    m_ServiceDisplayName = strServiceName;
    m_ServiceName = strServiceName;
}

//一键自助安装服务
void CWindowsService::Run()
{
    BOOL bNT = FALSE;
    BOOL bInstalled = FALSE;
    int dwCurrentState = 0;

    SC_HANDLE hService, hScm;
    hScm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);

    if (hScm)
    {
        bNT = TRUE;
        hService = OpenService(hScm, m_ServiceName.c_str(), GENERIC_READ);
        if (hService)
        {
            bInstalled = TRUE;

            SERVICE_STATUS ServiceStatus;
            if (QueryServiceStatus(hService, &ServiceStatus))
            {
                dwCurrentState = ServiceStatus.dwCurrentState;
                if (dwCurrentState == SERVICE_START_PENDING)
                {
                    CloseServiceHandle(hService);
                    CloseServiceHandle(hScm);

                    char chServiceName[256] = "";
                    strcpy_s(chServiceName, m_ServiceName.c_str());
                    const SERVICE_TABLE_ENTRY servicetable[] =
                    {
                        { chServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
                        { NULL,NULL }
                    };
                    BOOL success;
                    success = StartServiceCtrlDispatcher(servicetable);
                    if (!success)
                    {
                        int nError = GetLastError();
                        TCHAR buffer[1000];
                        _stprintf_s(buffer, _T("启动服务出错,错误码:%d"), nError);
                        MessageBox(0, buffer, m_ServiceName.c_str(), MB_OK);
                    }
                    return ;
                }
            }
            CloseServiceHandle(hService);
        }
        CloseServiceHandle(hScm);
    }

    if (!bInstalled)
    {
        if (MessageBox(0, _T("是否安装服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES)
        {
            if (!Install(dwCurrentState))
            {
                MessageBox(0, _T("安装服务失败"), m_ServiceName.c_str(), MB_OK);
                return;
            }
        }
        else
            return ;
    }

    if (dwCurrentState == SERVICE_STOPPED && (MessageBox(0, _T("启动服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES))
    {
        if (!Start())
        {
            MessageBox(0, _T("启动服务失败"), m_ServiceName.c_str(), MB_OK);
        }

        return;
    }

    if (dwCurrentState == SERVICE_STOPPED && (MessageBox(0, _T("卸载服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES))
    {
        if (!Uninstall())
        {
            MessageBox(0, _T("卸载服务失败"), m_ServiceName.c_str(), MB_OK);
        }
        return ;
    }

    if (dwCurrentState != SERVICE_STOPPED && (MessageBox(0, _T("停止服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES))
    {
        if (!Stop())
        {
            MessageBox(0, _T("停止服务失败"), m_ServiceName.c_str(), MB_OK);
        }
        return;
    }

    if (dwCurrentState == SERVICE_STOPPED)
        return ;
}

//安装服务
bool CWindowsService::Install(int & dwCurrentState)
{
    SC_HANDLE hService, hScm;

    hScm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
    if (!hScm)
    {
        return false;
    }
    int nStartMode = SERVICE_AUTO_START;

    if (MessageBox(0, _T("自动运行服务?"), m_ServiceName.c_str(), MB_YESNO | MB_ICONQUESTION) == IDYES)
    {
        nStartMode = SERVICE_AUTO_START;
    }

    TCHAR buffer[MAX_PATH + 3];
    buffer[0] = '"';
    DWORD written = GetModuleFileName(0, buffer + 1, MAX_PATH);
    if (!written)
    {
        CloseServiceHandle(hScm);
        MessageBox(0, _T("创建服务失败,未能获取应用程序当前的路径"), m_ServiceName.c_str(), MB_ICONSTOP);
        return false;
    }
    buffer[written + 1] = '"';
    buffer[written + 2] = 0;

    hService = CreateService(hScm, m_ServiceName.c_str(),
        m_ServiceDisplayName.c_str(),
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, nStartMode,
        SERVICE_ERROR_NORMAL,
        buffer,
        0, 0, NULL, 0, 0);
    if (!hService)
    {
        CloseServiceHandle(hScm);
        return false;
    }

    SERVICE_DESCRIPTION description;
    memset(&description, 0, sizeof(SERVICE_DESCRIPTION));
    TCHAR szdescription[100];
    memset(szdescription, 0, sizeof(TCHAR) * 100);
    _stprintf_s(szdescription, 100, _T("%s"), m_ServiceName.c_str());//服务名称
    description.lpDescription = szdescription;
    ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &description);

    CloseServiceHandle(hService);
    CloseServiceHandle(hScm);
    dwCurrentState = SERVICE_STOPPED;

    return true;
}

//卸载服务
bool CWindowsService::Uninstall()
{
    SC_HANDLE hService, hScm;
    hScm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
    if (!hScm)
    {
        return false;
    }
    hService = OpenService(hScm, m_ServiceName.c_str(), SERVICE_ALL_ACCESS);
    if (!hService)
    {
        CloseServiceHandle(hScm);
        return false;
    }
    DeleteService(hService);
    CloseServiceHandle(hService);
    CloseServiceHandle(hScm);

    return true;
}

//启动服务
bool CWindowsService::Start()
{
    SC_HANDLE hService, hScm;
    hScm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
    if (!hScm)
    {
        return false;
    }
    hService = OpenService(hScm, m_ServiceName.c_str(), SERVICE_ALL_ACCESS);
    if (!hService)
    {
        CloseServiceHandle(hScm);
        return false;
    }
    if (StartService(hService, 0, NULL) == 0)
    {
        DWORD dwerr = GetLastError();
        Sleep(1);
    }
    CloseServiceHandle(hService);
    CloseServiceHandle(hScm);

    return true;
}

//停止服务
bool CWindowsService::Stop()
{
    SC_HANDLE hService, hScm;
    hScm = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
    if (!hScm)
    {
        return false;
    }
    hService = OpenService(hScm, m_ServiceName.c_str(), SERVICE_ALL_ACCESS);
    if (!hService)
    {
        CloseServiceHandle(hScm);
        return false;
    }
    SERVICE_STATUS status;
    ControlService(hService, SERVICE_CONTROL_STOP, &status);
    CloseServiceHandle(hService);
    CloseServiceHandle(hScm);

    return true;
}

//创建服务主要处理逻辑
void CWindowsService::ServiceMain(DWORD argc, LPTSTR * argv)
{
    BOOL success;
    g_pWindowsService->m_nServiceStatusHandle = RegisterServiceCtrlHandler(g_pWindowsService->m_ServiceName.c_str(), (LPHANDLER_FUNCTION)(ServiceCtrlHandler));
    if (!g_pWindowsService->m_nServiceStatusHandle)
        return;

    success = g_pWindowsService->UpdateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 3000);
    if (!success)
        return;

    g_pWindowsService->m_EventkillService = CreateEvent(0, TRUE, FALSE, 0);//创建时间等待结束
    if (g_pWindowsService->m_EventkillService == NULL)
        return;

    success = g_pWindowsService->UpdateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, 1000);
    if (!success)
        return;

    success = g_pWindowsService->StartServiceThread(); //开启主线程
    if (!success)
        return;

    g_pWindowsService->m_dwServiceCurrentStatus = SERVICE_RUNNING;
    success = g_pWindowsService->UpdateServiceStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
    if (!success)
        return;

    WaitForSingleObject(g_pWindowsService->m_EventkillService, INFINITE); //等待结束
    CloseHandle(g_pWindowsService->m_EventkillService);
    WaitForSingleObject(g_pWindowsService->m_hServiceThread, INFINITE); // 更待结束线程结束
    CloseHandle(g_pWindowsService->m_hServiceThread);
    g_pWindowsService->UpdateServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
}

//接受servicecontrol 命令
void CWindowsService::ServiceCtrlHandler(DWORD nControlCode)
{
    BOOL success;
    switch (nControlCode)
    {
    case SERVICE_CONTROL_SHUTDOWN:
    case SERVICE_CONTROL_STOP:
        g_pWindowsService->m_dwServiceCurrentStatus = SERVICE_STOP_PENDING;
        success = g_pWindowsService->UpdateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 3000);
        g_pWindowsService->KillService();
        return;
    default:
        break;
    }
    g_pWindowsService->UpdateServiceStatus(g_pWindowsService->m_dwServiceCurrentStatus, NO_ERROR, 0, 0, 0);
}

//更新服务状态 更新失败即结束服务
BOOL CWindowsService::UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
{
    BOOL success;
    SERVICE_STATUS nServiceStatus;
    nServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    nServiceStatus.dwCurrentState = dwCurrentState;
    if (dwCurrentState == SERVICE_START_PENDING)
    {
        nServiceStatus.dwControlsAccepted = 0;
    }
    else
    {
        nServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
            | SERVICE_ACCEPT_SHUTDOWN;
    }
    if (dwServiceSpecificExitCode == 0)
    {
        nServiceStatus.dwWin32ExitCode = dwWin32ExitCode;
    }
    else
    {
        nServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
    }
    nServiceStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
    nServiceStatus.dwCheckPoint = dwCheckPoint;
    nServiceStatus.dwWaitHint = dwWaitHint;

    success = SetServiceStatus(m_nServiceStatusHandle, &nServiceStatus);
    if (!success)
    {
        KillService();
        return success;
    }
    else
    {
        return success;
    }
}

//创建主窗口线程
BOOL CWindowsService::StartServiceThread()
{
    DWORD id;
    m_hServiceThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ServiceExecutionThread, 0, 0, &id);
    if (m_hServiceThread == 0)
    {
        return FALSE;
    }
    else
    {
        m_bServiceRunning = TRUE;
        return true;
    }
}

//创建服务主线程(应用主要启动)
DWORD CWindowsService::ServiceExecutionThread(LPDWORD param)
{
    BOOL res = TRUE;

    //启动
    CServer *pServer = new CServer;
    g_pWindowsService->m_bServiceRunning = pServer->Create();


    if (!g_pWindowsService->m_bServiceRunning)
    {
        return 0;
    }
    else
    {
        g_pWindowsService->m_hMain = pServer->GetMainHwnd();

    }

    MSG msg;
    while (GetMessage(&msg, 0, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    SetEvent(g_pWindowsService->m_EventkillService);
    return 0;
}

// 停止服务 即结束主窗口线程 设置状态失败或是收到STOP SERVICE 命令调用此函数
void CWindowsService::KillService()
{
    if (m_hMain != NULL)
        PostMessage(m_hMain, WM_CLOSE, 0, 0); //结束窗口
    m_bServiceRunning = FALSE;
}
  • 需要修改地方
    WindowsService.cpp
    //创建服务主线程(应用主要启动)
    DWORD CWindowsService::ServiceExecutionThread(LPDWORD param)
    修改该函数里面的
    //启动
    CServer *pServer = new CServer;
    g_pWindowsService->m_bServiceRunning = pServer->Create();

这里就是服务真正需要运行的代码,对应修改。

  • 调用方式

#include "stdafx.h"
#include "WindowsService.h"

#ifndef _DEBUG
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
#endif

int _tmain(int argc, _TCHAR* argv[])
{
#ifdef _DEBUG//调试
    //调试使用
#else//服务(发布使用)
    //设置服务名称
    string strServiceName = "ServiceName";
    g_pWindowsService = new CWindowsService(strServiceName);
    g_pWindowsService->Run();//注册服务,启动
#endif

    return 0;
}
展开阅读全文

没有更多推荐了,返回首页