安装、启动和挺住服务程序

class WindowsService {
private:
    SERVICE_STATUS* ServiceStatus = NULL;
    SERVICE_STATUS_HANDLE* ServieStutusHandle = NULL;
    DWORD dwCheckPoint = 1;

public:
    string ServiceName;
    string ServicePath;
    string ServiceDescription;

    WindowsService(string serviceName, string servicePath, string serviceDescription)
        :ServiceName(serviceName), ServicePath(servicePath), ServiceDescription(serviceDescription) {
    }

    /// <summary>
    /// 检查服务是否已存在
    /// </summary>
    /// <returns>
    /// 返回码:
    /// NO_ERROR,服务存在;
    /// ERROR_SERVICE_DOES_NOT_EXIST,服务不存在;
    /// 错误码(详见winerror.h)
    /// </returns>
    DWORD IsInstalled() {
        SC_HANDLE schSCManager = NULL;
        SC_HANDLE schService = NULL;
        DWORD err = NO_ERROR;

        schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if (NULL == schSCManager) {
            err = GetLastError();
            goto End;
        }

        schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_QUERY_STATUS);
        if (schService == NULL) {
            err = GetLastError();
            goto End;
        }

End:
        if (schService != NULL) {
            CloseServiceHandle(schService);
        }
        if (schSCManager != NULL) {
            CloseServiceHandle(schSCManager);
        }
        return err;
    }

    /// <summary>
    /// 安装服务
    /// </summary>
 /// <param name="startType">启动方式:SERVICE_AUTO_START、SERVICE_BOOT_START、SERVICE_DEMAND_START、SERVICE_DISABLED、SERVICE_SYSTEM_START</param>
    /// <param name="startType">服务运行失败后是否自动重启</param>
    /// <returns>
    /// 返回码:
    /// NO_ERROR,服务安装成功;
    /// 错误码(详见winerror.h)
    /// </returns>
    DWORD Install(DWORD startType = SERVICE_AUTO_START, bool autoRestart = false) {
        SC_HANDLE schSCManager = NULL;
        SC_HANDLE schService = NULL;
        DWORD err = NO_ERROR;
        schSCManager = OpenSCManager(
                           NULL,
                           NULL,

                           SC_MANAGER_ALL_ACCESS);

        if (NULL == schSCManager) {
            err = GetLastError();
            goto End;
        }
        schService = CreateServiceA(
                         schSCManager,
                         ServiceName.c_str(),
                         ServiceName.c_str(),
                         SERVICE_ALL_ACCESS,
                         SERVICE_WIN32_OWN_PROCESS,
                         startType,
                         SERVICE_ERROR_NORMAL,
                         ServicePath.c_str(),
                         NULL,
                         NULL,
                         NULL,
                         NULL,
                         NULL);
        if (schService == NULL) {
            err = GetLastError();
            goto End;
        }

        //设置服务备注信息
        if (!ServiceDescription.empty()) {
            SERVICE_DESCRIPTIONA sd;
            sd.lpDescription = (LPSTR)(ServiceDescription.c_str());
            if (!ChangeServiceConfig2A(schService, SERVICE_CONFIG_DESCRIPTION, &sd)) {
                err = GetLastError();
                goto End;
            }
        }

        //设置服务失败时自动启动
        if (autoRestart) {
            SERVICE_FAILURE_ACTIONS info;
            SC_ACTION action[1];
            action[0].Type = SC_ACTION_RESTART;
            action[0].Delay = 0;
            info.dwResetPeriod = 0; //出现一次失败后,0 ms后重新计算第一次失败
            info.lpRebootMsg = NULL;
            info.lpCommand = NULL;
            info.cActions = 1; // action array个数
            info.lpsaActions = action; // action array指针
            if (!ChangeServiceConfig2(schService, SERVICE_CONFIG_FAILURE_ACTIONS, &info)) {
                err = GetLastError();
                goto End;
            }
        }

End:
        if (schService != NULL) {
            CloseServiceHandle(schService);
        }
        if (schSCManager != NULL) {
            CloseServiceHandle(schSCManager);
        }
        return err;
    }

    /// <summary>
    /// 卸载服务
    /// </summary>
    /// <returns>
    /// 返回码:
    /// NO_ERROR,服务卸载成功;
    /// 错误码(详见winerror.h)
    /// </returns>
    DWORD Uninstall() {
        SC_HANDLE schSCManager = NULL;
        SC_HANDLE schService = NULL;
        DWORD err = NO_ERROR;

        schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if (NULL == schSCManager) {
            err = GetLastError();
            goto End;
        }

        schService = OpenServiceA(schSCManager, ServiceName.c_str(), DELETE);
        if (schService == NULL) {
            err = GetLastError();
            goto End;
        }

        if (!DeleteService(schService)) {
            err = GetLastError();
            goto End;
        }

End:
        if (schService != NULL) {
            CloseServiceHandle(schService);
        }
        if (schSCManager != NULL) {
            CloseServiceHandle(schSCManager);
        }
        return err;
    }

    /// <summary>
    /// 启动服务
    /// </summary>
    /// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
    /// <param name="dwTimeout">停止服务等待超时时间(毫秒)</param>
    /// <returns>
    /// 返回码:
    /// NO_ERROR,服务启动成功,服务状态需要通过GetStatus函数获取;
    /// 错误码(详见winerror.h)
    /// </returns>
    DWORD Start(SERVICE_STATUS_PROCESS& ssStatus, DWORD dwTimeout = 30000) {
        SC_HANDLE schSCManager = NULL;
        SC_HANDLE schService = NULL;
        DWORD dwBytesNeeded;
        DWORD dwStartTickCount;
        DWORD err = NO_ERROR;

        schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if (NULL == schSCManager) {
            err = GetLastError();
            goto End;
        }

        schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
        if (schService == NULL) {
            err = GetLastError();
            goto End;
        }

        if (!StartService(schService, 0, NULL)) {
            err = GetLastError();
            goto End;
        }


 if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {

            err = GetLastError();
            goto End;
        }

        dwStartTickCount = GetTickCount();
        while (ssStatus.dwCurrentState == SERVICE_START_PENDING) {
            Sleep(1000);
            if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
                err = GetLastError();
                goto End;
            }


            if (GetTickCount() - dwStartTickCount > dwTimeout) {
                break;
            }
        }

End:
        if (schService != NULL) {
            CloseServiceHandle(schService);
        }
        if (schSCManager != NULL) {
            CloseServiceHandle(schSCManager);
        }


        return err;
    }


    /// <summary>
    /// 停止服务
    /// </summary>
    /// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
    /// <param name="dwTimeout">停止服务等待超时时间(毫秒)</param>
    /// <returns>
    /// 返回码:
    /// NO_ERROR,服务停止成功,服务状态需要通过GetStatus函数获取;
    /// 错误码(详见winerror.h)
    /// </returns>
    DWORD Stop(SERVICE_STATUS_PROCESS& ssStatus, DWORD dwTimeout = 30000) {
        SC_HANDLE schSCManager = NULL;
        SC_HANDLE schService = NULL;
        DWORD dwBytesNeeded;
        DWORD dwStartTickCount;
        DWORD err = NO_ERROR;


        schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if (NULL == schSCManager) {
            err = GetLastError();
            goto End;
        }
        schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
        if (schService == NULL) {
            err = GetLastError();
            goto End;
        }


        if (!ControlService(schService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssStatus)) {
            err = GetLastError();
            goto End;
        }


        dwStartTickCount = GetTickCount();
        while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
            Sleep(1000);
            if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
                err = GetLastError();
                goto End;
            }

            if (GetTickCount() - dwStartTickCount > dwTimeout) {
                break;
            }
        }


End:
        if (schService != NULL) {
            CloseServiceHandle(schService);
        }
        if (schSCManager != NULL) {
            CloseServiceHandle(schSCManager);
        }
        return err;
    }

    /// <summary>
    /// 获取服务状态
    /// </summary>
    /// <param name="ssStatus">服务状态,当返回值是NO_ERROR时有效</param>
    /// <returns>
    /// 返回码:
    /// NO_ERROR,操作成功;
    /// 错误码(详见winerror.h)
    /// </returns>
    DWORD GetStatus(SERVICE_STATUS_PROCESS& ssStatus) {
        SC_HANDLE schSCManager = NULL;
        SC_HANDLE schService = NULL;
        DWORD dwBytesNeeded;
        DWORD err = NO_ERROR;

        schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if (NULL == schSCManager) {
            err = GetLastError();
            goto End;
        }

        schService = OpenServiceA(schSCManager, ServiceName.c_str(), SERVICE_ALL_ACCESS);
        if (schService == NULL) {
            err = GetLastError();
            goto End;
        }

 if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {
            err = GetLastError();
            goto End;
        }

End:
        if (schService != NULL) {
            CloseServiceHandle(schService);
        }
        if (schSCManager != NULL) {
            CloseServiceHandle(schSCManager);
        }
        return err;

    }

    /// <summary>
    /// Binds the service status.
    /// </summary>
    /// <param name="serviceStatus">The service status.</param>
    /// <param name="servieStutusHandle">The servie stutus handle.</param>
    void BindServiceStatus(SERVICE_STATUS& serviceStatus, SERVICE_STATUS_HANDLE& servieStutusHandle) {
        ServiceStatus = &serviceStatus;
        ServieStutusHandle = &servieStutusHandle;
    }

    /// <summary>
    /// 修改服务状态,
    /// 调用此函数之前处理先调用过一次BindServiceStatus才行
    /// </summary>
    /// <param name="dwCurrentState">服务状态</param>
    /// <param name="dwWaitHint">状态变更预计时间(毫秒)</param>
    /// <returns>
    /// 返回码:
    /// NO_ERROR,操作执行成功;
    /// 错误码(详见winerror.h)
    /// </returns>
    DWORD ReportServiceStatus(DWORD dwCurrentState, DWORD dwWaitHint, DWORD dwWin32ExitCode = NO_ERROR, DWORD dwServiceSpecificExitCode = NO_ERROR) {
        DWORD err = NO_ERROR;

        ServiceStatus->dwCurrentState = dwCurrentState;
        ServiceStatus->dwWin32ExitCode = dwWin32ExitCode;
        ServiceStatus->dwServiceSpecificExitCode = dwServiceSpecificExitCode;
        ServiceStatus->dwWaitHint = dwWaitHint;
        if (dwCurrentState == SERVICE_START_PENDING) {
            ServiceStatus->dwControlsAccepted = 0;
        } else {
            ServiceStatus->dwControlsAccepted = SERVICE_ACCEPT_STOP;
        }
        if (dwCurrentState == SERVICE_RUNNING || dwCurrentState == SERVICE_STOPPED) {
            ServiceStatus->dwCheckPoint = 0;
        } else {
            ServiceStatus->dwCheckPoint = dwCheckPoint++;
        }
        if (!SetServiceStatus(*ServieStutusHandle, ServiceStatus)) {
            err = GetLastError();
            return err;
        }

        return err;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值