• Windows NTService 后台框架封装


      对于后台运行的程序,比如基于C/S架构的服务器、各种监控系统的程序、或者是程序额外的功能需要后台运行来实现,在Windows平台中,服务经常会用到,这种对于需要24×7运行的程序是必备的,至少本人经常需要运用windows服务来搭建后台程序。于是查阅网上的各种资料,发现有不少的参考实例,但是使用起来有各种问题,不少是这些作者或者使用者对Windows NT Service API接口运用的不熟练或者不清楚,导致自己花费很多时间在理解这些错误的实例当中,不过折腾到最后,还是从错误中得到不少教训的。所以为了方便以后能够直接使用,不再做重复的工作,便在工作之余将Windows NT Service API接口进行了二次封装并简单的测试通过,发上来也让大家使用并指正其中的错误。

      当然,有更权威的参考实例。http://msdn.microsoft.com/en-us/library/windows/desktop/bb540476(v=vs.85).aspx

      废话不多说, 先直接贴上代码,希望不要被贱笑了...

      NTService.h

    #ifndef _NTSERVICE_H_
    #define _NTSERVICE_H_
    
    ///服务启动类型定义
    enum SERVICE_STARTUP_TYPE
    {
        //禁用不可启动
        SST_DISABLED=0,
    
        //随系统启动自动启动
        SST_AUTO_START=1,
    
        //命令/手动启动
        SST_DEMAND_START=2
    };
    
    ///服务执行的任务对象
    class ServiceTask
    {
    public:
        ServiceTask(){}
        virtual ~ServiceTask(){}
    
    public:
        ///服务初始化通知
        ///@return 成功返回0, 否则-1
        ///@remark 完成后需及时返回, 不能长时间阻塞
        virtual int OnInit(int argc, char **argv){return 0;}
    
        ///服务启动通知
        ///@remark 服务启动阻塞执行此过程, 直至服务停止/关闭
        virtual void OnStart(){}
    
        ///服务停止通知
        ///@remark OnStart结束返回, 服务变为停止状态
        virtual void OnStop(){}
    
        ///服务暂停通知
        ///@remark OnStart暂停执行, 服务变为暂停状态
        virtual void OnPause(){}
    
        ///被暂停的服务恢复通知
        ///@remark OnStart恢复执行, 服务变为恢复状态
        virtual void OnContinue(){}
    
        ///服务被强制关闭通知
        ///@remark 通常是OS关闭时发生
        virtual void OnShutdown(){}
    };
    
    class NTServiceImpl;
    
    ///服务接口控制对象
    class NTService
    {
    public:
        ///@param name服务名称
        ///@param canstop是否可停止
        ///@param canshutdown是否可关闭
        ///@param canpausecontinue是否可暂停继续
        NTService(const char *name,
            bool canstop=true,
            bool canshutdown=true,
            bool canpausecontinue=false);
    
        ~NTService();
    
    public:
        ///检查服务是否安装
        bool IsInstalled();
    
        ///安装服务
        ///@param display_name服务显示的名称
        ///@param type服务启动类型
        ///@return 成功返回0, 否则-1
        int Install(const char *display_name, SERVICE_STARTUP_TYPE type);
    
        ///卸载服务
        ///@return 成功返回0, 否则-1
        int UnInstall();
    
        ///设置服务启动类型
        ///@return 成功返回0, 否则-1
        int SetStartupType(SERVICE_STARTUP_TYPE type);
    
        ///更新服务描述信息
        ///@return 成功返回0, 否则-1
        int UpdateDesc(const char *desc);
    
        ///启动服务
        ///@return 成功返回0, 否则-1
        ///@param argc启动参数个数
        ///@param argv启动参数列表
        int Start(int argc=0, const char **argv=0);
    
        ///停止服务
        ///@return 成功返回0, 否则-1
        int Stop();
    
        ///获取服务当前状态
        ///@return 成功返回状态值, 否则-1
        int GetCurrentStatus();
    
    public:
        ///系统启动服务调用
        ///@remark 不可主动调用
        int Run(ServiceTask &service);
    
    private:
        NTServiceImpl *m_impl;
    };
    
    #endif//_NTSERVICE_H_

      NTServiceImpl.h

      

    #ifndef _NTSERVICE_IMPL_H_
    #define _NTSERVICE_IMPL_H_
    #include "NTService.h"
    #include <Windows.h>
    #include <string>
    
    class NTServiceImpl
    {
    public:
        NTServiceImpl(const char *name,
            bool canstop, 
            bool canshutdown, 
            bool canpausecontinue);
    
        ~NTServiceImpl();
    
    public:
        bool IsInstalled();
        int Install(const char *display_name, SERVICE_STARTUP_TYPE type);
        int UnInstall();
        int SetStartupType(SERVICE_STARTUP_TYPE type);
        int UpdateDesc(const char *desc);
        int Start(int argc, const char **argv);
        int Stop();
        int GetCurrentStatus();
    
        int Run(ServiceTask &service);
    
    private:
        std::string m_name;
        bool m_canstop;
        bool m_canshutdown;
        bool m_canpausecontinue;
    };
    
    class NTServiceManager
    {
    private:
        NTServiceManager();
        ~NTServiceManager();
    
    public:
        static bool IsInstalled(const char *name);
        static int Install(const char *name, const char *display_name, SERVICE_STARTUP_TYPE type);
        static int UnInstall(const char *name);
        static int SetStartupType(const char *name, SERVICE_STARTUP_TYPE type);
        static int UpdateDesc(const char *name, const char *desc);
        static int Start(const char *name, int argc, const char **argv);
        static int Stop(const char *name);
        static int GetCurrentStatus(const char *name);
    
    private:
        static int GetRealStartupType(SERVICE_STARTUP_TYPE type);
    };
    
    class NTServiceHandler
    {
    private:
        NTServiceHandler(const std::string &name,
            bool canstop,
            bool canshutdown,
            bool canpausecontinue,
            ServiceTask &service);
    
        ~NTServiceHandler();
    
    public:
        static void CreateInstance(const std::string &name,
            bool canstop,
            bool canshutdown,
            bool canpausecontinue,
            ServiceTask &service)
        {
            DestroyInstance();
            m_this =new NTServiceHandler(name, canstop, canshutdown, canpausecontinue, service);
        }
        static NTServiceHandler *GetInstance()
        {
            return m_this;
        }
        static void DestroyInstance()
        {
            if (m_this)
            {
                delete m_this;
                m_this = 0;
            }
        }
    
    public:
        int Run();
    
    private:
        static void ServiceMainHandler(DWORD argc, LPSTR *argv);
        static void ServiceCtrlHandler(DWORD ctrl);
    
    private:
        void NTS_Start(DWORD argc, LPSTR *argv);
        void NTS_Stop();
        void NTS_Pause();
        void NTS_Continue();
        void NTS_Shutdown();
    
        void SetServiceStatus(DWORD dwCurrentState,
            DWORD dwWin32ExitCode=NO_ERROR,
            DWORD dwWaitHint=0);
    
        int OnInit(int argc, char **argv);
        void OnStart();
        void OnStop();
        void OnPause();
        void OnContinue();
        void OnShutdown();
        
    private:
        std::string m_name;
        ServiceTask &m_service;
    
        SERVICE_STATUS m_status;
        SERVICE_STATUS_HANDLE m_status_handle;
        
        static NTServiceHandler *m_this;
    };
    
    NTServiceHandler *NTServiceHandler::m_this = 0;
    
    #endif//_NTSERVICE_IMPL_H_
    View Code

      NTServiceImpl.cpp

    #include "NTServiceImpl.h"
    #include <assert.h>
    
    NTService::NTService(const char *name,
        bool canstop, 
        bool canshutdown, 
        bool canpausecontinue)
    {
        m_impl = new NTServiceImpl(name, canstop, canshutdown, canpausecontinue);
    }
    NTService::~NTService()
    {
        if (m_impl)
        {
            delete m_impl;
            m_impl = 0;
        }
    }
    bool NTService::IsInstalled()
    {
        return m_impl->IsInstalled();
    }
    int NTService::Install(const char *display_name, SERVICE_STARTUP_TYPE type)
    {
        return m_impl->Install(display_name, type);
    }
    int NTService::UnInstall()
    {
        return m_impl->UnInstall();
    }
    int NTService::SetStartupType(SERVICE_STARTUP_TYPE type)
    {
        return m_impl->SetStartupType(type);
    }
    int NTService::UpdateDesc(const char *desc)
    {
        return m_impl->UpdateDesc(desc);
    }
    int NTService::Start(int argc, const char **argv)
    {
        return m_impl->Start(argc, argv);    
    }
    int NTService::Stop()
    {
        return m_impl->Stop();    
    }
    int NTService::GetCurrentStatus()
    {
        return m_impl->GetCurrentStatus();
    }
    int NTService:: Run(ServiceTask &service)
    {
        return m_impl->Run(service);
    }
    
    NTServiceImpl::NTServiceImpl(const char *name,
        bool canstop, 
        bool canshutdown, 
        bool canpausecontinue)
        : m_name(name)
    {
        m_canstop = canstop;
        m_canshutdown = canshutdown;
        m_canpausecontinue = canpausecontinue;
    }
    
    NTServiceImpl::~NTServiceImpl()
    {
    }
    
    bool NTServiceImpl::IsInstalled()
    {
        return NTServiceManager::IsInstalled(m_name.c_str());
    }
    
    int NTServiceImpl::Install(const char *display_name, SERVICE_STARTUP_TYPE type)
    {
        return NTServiceManager::Install(m_name.c_str(), display_name, type);
    }
    
    int NTServiceImpl::UnInstall()
    {
        return NTServiceManager::UnInstall(m_name.c_str());
    }
    
    int NTServiceImpl::Start(int argc, const char **argv)
    {
        return NTServiceManager::Start(m_name.c_str(), argc, argv);
    }
    
    int NTServiceImpl::Stop()
    {
        return NTServiceManager::Stop(m_name.c_str());
    }
    
    int NTServiceImpl::SetStartupType(SERVICE_STARTUP_TYPE type)
    {
        return NTServiceManager::SetStartupType(m_name.c_str(), type);
    }
    
    int NTServiceImpl::UpdateDesc(const char *desc)
    {
        return NTServiceManager::UpdateDesc(m_name.c_str(), desc);
    }
    
    int NTServiceImpl::GetCurrentStatus()
    {
        return NTServiceManager::GetCurrentStatus(m_name.c_str());
    }
    
    int NTServiceImpl::Run(ServiceTask &service)
    {
        NTServiceHandler::CreateInstance(m_name, m_canstop, m_canshutdown, m_canpausecontinue, service);
        NTServiceHandler *handler = NTServiceHandler::GetInstance();
        return handler ? handler->Run() : -1;
    }
    
    bool NTServiceManager::IsInstalled(const char *name)
    {
        assert(name);
    
        bool result = false;
        SC_HANDLE scmanager = 0;
        SC_HANDLE service = 0;
    
        scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
        if (!scmanager)
        {
            goto __Cleanup;
        }
    
        service = ::OpenService(scmanager, name, SERVICE_QUERY_STATUS);
    
    __Cleanup:
        if (service)
        {
            result = true;
            ::CloseServiceHandle(service);
        }
        if (scmanager)
        {
            ::CloseServiceHandle(scmanager);
        }
    
        return result;
    }
    
    int NTServiceManager::Install(const char *name, const char *display_name, SERVICE_STARTUP_TYPE type)
    {
        assert(name && display_name);
    
        int result = -1;
        SC_HANDLE scmanager = 0;
        SC_HANDLE service = 0;
    
        scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE);
        if (!scmanager)
        {
            goto __Cleanup;
        }
    
        char file_path[MAX_PATH] = {0};
        ::GetModuleFileName(NULL, file_path, MAX_PATH);
    
        int startup_type = GetRealStartupType(type);
    
        service = CreateService( 
            scmanager,                                            // SCM database 
            name,                                                    // name of service 
            display_name,                                        // service name to display 
            SERVICE_ALL_ACCESS,                            // desired access 
            SERVICE_WIN32_OWN_PROCESS,            // service type 
            startup_type,                                            // start type 
            SERVICE_ERROR_NORMAL,                    // error control type 
            file_path,                                                // path to service's binary 
            NULL,                                                    // no load ordering group 
            NULL,                                                    // no tag identifier 
            NULL,                                                    // no dependencies 
            NULL,                                                    // LocalSystem account 
            NULL);                                                    // no password
    
    __Cleanup:
        if (service)
        {
            result = 0;
            ::CloseServiceHandle(service);
        }
        if (scmanager)
        {
            ::CloseServiceHandle(scmanager);
        }
    
        return result;
    }
    
    int NTServiceManager::UnInstall(const char *name)
    {
        assert(name);
    
        int result = -1;
        SC_HANDLE scmanager = 0;
        SC_HANDLE service = 0;
        SERVICE_STATUS status = {0};
    
        scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
        if (!scmanager)
        {
            goto __Cleanup;
        }
    
        service = ::OpenService(scmanager, name, SERVICE_STOP|SERVICE_QUERY_STATUS|DELETE);
        if (!service)
        {
            goto __Cleanup;
        }
    
        if (ControlService(service, SERVICE_CONTROL_STOP, &status))
        {
            ::Sleep(1000);
    
            while (QueryServiceStatus(service, &status))
            {
                if (status.dwCurrentState != SERVICE_STOP_PENDING)
                {
                    break;
                }
                else
                {
                    Sleep(1000);
                }
            }
        }
    
        if (DeleteService(service))
        {
            result = 0;
        }
    
    __Cleanup:
        if (service)
        {
            ::CloseServiceHandle(service);
        }
        if (scmanager)
        {
            ::CloseServiceHandle(scmanager);
        }
    
        return result;
    }
    
    int NTServiceManager::SetStartupType(const char *name, SERVICE_STARTUP_TYPE type)
    {
        assert(name);
    
        int result = -1;
        SC_HANDLE scmanager = 0;
        SC_HANDLE service = 0;
    
        scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
        if (!scmanager)
        {
            goto __Cleanup;
        }
    
        service = ::OpenService(scmanager, name, SERVICE_CHANGE_CONFIG);
        if (!service)
        {
            goto __Cleanup;
        }
    
        int startup_type = GetRealStartupType(type);
    
        BOOL csc_result = ChangeServiceConfig( 
            service,                                        // handle of service 
            SERVICE_NO_CHANGE,                // service type: no change 
            startup_type,                                // service start type 
            SERVICE_NO_CHANGE,                // error control: no change 
            NULL,                                        // binary path: no change 
            NULL,                                        // load order group: no change 
            NULL,                                        // tag ID: no change 
            NULL,                                        // dependencies: no change 
            NULL,                                        // account name: no change 
            NULL,                                        // password: no change 
            NULL);                                        // display name: no change
    
        if (csc_result)
        {
            result = 0;
        }
    
    __Cleanup:
        if (service)
        {
            ::CloseServiceHandle(service);
        }
        if (scmanager)
        {
            ::CloseServiceHandle(scmanager);
        }
    
        return result;
    }
    
    int NTServiceManager::UpdateDesc(const char *name, const char *desc)
    {
        assert(name);
    
        int result = -1;
        SC_HANDLE scmanager = 0;
        SC_HANDLE service = 0;
        SERVICE_DESCRIPTION sd = {0};
        sd.lpDescription = (char *)desc;
    
        scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
        if (!scmanager)
        {
            goto __Cleanup;
        }
    
        service = ::OpenService(scmanager, name, SERVICE_CHANGE_CONFIG);
        if (!service)
        {
            goto __Cleanup;
        }
    
        if (ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &sd))
        {
            result = 0;
        }
    
    __Cleanup:
        if (service)
        {
            ::CloseServiceHandle(service);
        }
        if (scmanager)
        {
            ::CloseServiceHandle(scmanager);
        }
    
        return result;
    }
    
    int NTServiceManager::Start(const char *name, int argc, const char **argv)
    {
        assert(name);
    
        int result = -1;
        SC_HANDLE scmanager = 0;
        SC_HANDLE service = 0;
        SERVICE_STATUS status = {0};
        DWORD dwStartTickCount = 0;
        DWORD dwOldCheckPoint = 0;
        DWORD dwWaitTime = 0;
    
        scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
        if (!scmanager)
        {
            goto __Cleanup;
        }
    
        service = ::OpenService(scmanager, name, SERVICE_ALL_ACCESS);
        if (!service)
        {
            goto __Cleanup;
        }
    
        if (!QueryServiceStatus(service, &status))
        {
            goto __Cleanup;
        }
    
        if(status.dwCurrentState!=SERVICE_STOPPED 
            && status.dwCurrentState!=SERVICE_STOP_PENDING)
        {
            goto __Cleanup;
        }
    
        dwStartTickCount = GetTickCount();
        dwOldCheckPoint = status.dwCheckPoint;
        while (status.dwCurrentState == SERVICE_STOP_PENDING)
        {
            dwWaitTime = status.dwWaitHint / 10;
            if(dwWaitTime < 1000)
            {
                dwWaitTime = 1000;
            }
            else if (dwWaitTime > 10000)
            {
                dwWaitTime = 10000;
            }
            ::Sleep(dwWaitTime);
    
            if (!QueryServiceStatus(service, &status))
            {
                goto __Cleanup;
            }
    
            if (status.dwCheckPoint > dwOldCheckPoint)
            {
                dwStartTickCount = GetTickCount();
                dwOldCheckPoint = status.dwCheckPoint;
            }
            else
            {
                if ((GetTickCount()-dwStartTickCount) > status.dwWaitHint)
                {
                    goto __Cleanup;
                }
            }
        }
    
        if (!StartService(service, argc, argv))
        {
            goto __Cleanup;
        }
    
        if (!QueryServiceStatus(service, &status))
        {
            goto __Cleanup;
        }
    
        dwStartTickCount = GetTickCount();
        dwOldCheckPoint = status.dwCheckPoint;
        while (status.dwCurrentState == SERVICE_START_PENDING) 
        { 
            dwWaitTime = status.dwWaitHint / 10;
            if(dwWaitTime < 1000)
            {
                dwWaitTime = 1000;
            }
            else if (dwWaitTime > 10000)
            {
                dwWaitTime = 10000;
            }
            ::Sleep(dwWaitTime);
    
            if (!QueryServiceStatus(service, &status))
            {
                goto __Cleanup;
            }
    
            if (status.dwCheckPoint > dwOldCheckPoint)
            {
                dwStartTickCount = GetTickCount();
                dwOldCheckPoint = status.dwCheckPoint;
            }
            else
            {
                if ((GetTickCount()-dwStartTickCount) > status.dwWaitHint)
                {
                    break;
                }
            }
        } 
    
    __Cleanup:
        if (status.dwCurrentState==SERVICE_RUNNING)
        {
            result = 0;
        }
    
        if (service)
        {
            ::CloseServiceHandle(service);
        }
        if (scmanager)
        {
            ::CloseServiceHandle(scmanager);
        }
    
        return result;
    }
    
    int NTServiceManager::Stop(const char *name)
    {
        assert(name);
    
        int result = -1;
        SC_HANDLE scmanager = 0;
        SC_HANDLE service = 0;
        SERVICE_STATUS status = {0};
        DWORD dwStartTime = GetTickCount();
        DWORD dwTimeout = 30000;
        DWORD dwWaitTime = 0;
        
        scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
        if (!scmanager)
        {
            goto __Cleanup;
        }
    
        service = ::OpenService(scmanager, name, SERVICE_STOP|SERVICE_QUERY_STATUS);
        if (!service)
        {
            goto __Cleanup;
        }
    
        if (!QueryServiceStatus(service, &status))
        {
            goto __Cleanup;
        }
    
        if (status.dwCurrentState == SERVICE_STOPPED)
        {
            goto __Cleanup;
        }
    
        while (status.dwCurrentState == SERVICE_STOP_PENDING)
        {
            dwWaitTime = status.dwWaitHint / 10;
            if(dwWaitTime < 1000)
            {
                dwWaitTime = 1000;
            }
            else if (dwWaitTime > 10000)
            {
                dwWaitTime = 10000;
            }
            ::Sleep(dwWaitTime);
    
            if (!QueryServiceStatus(service, &status))
            {
                goto __Cleanup;
            }
    
            if (status.dwCurrentState == SERVICE_STOPPED)
            {
                goto __Cleanup;
            }
    
            if ((GetTickCount() - dwStartTime) > dwTimeout)
            {
                goto __Cleanup;
            }
        }
    
        if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
        {
            goto __Cleanup;
        }
    
        while (status.dwCurrentState != SERVICE_STOPPED)
        {
            ::Sleep(status.dwWaitHint);
    
            if (!QueryServiceStatus(service, &status))
            {
                goto __Cleanup;
            }
    
            if (status.dwCurrentState == SERVICE_STOPPED)        
            {
                goto __Cleanup;
            }
    
            if ( GetTickCount() - dwStartTime > dwTimeout )
            {
                goto __Cleanup;
            }
        }
    
    __Cleanup:
        if (status.dwCurrentState == SERVICE_STOPPED)
        {
            result = 0;
        }
    
        if (service)
        {
            ::CloseServiceHandle(service);
        }
        if (scmanager)
        {
            ::CloseServiceHandle(scmanager);
        }
    
        return result;
    }
    
    int NTServiceManager::GetCurrentStatus(const char *name)
    {
        assert(name);
    
        int result = -1;
        SC_HANDLE scmanager = 0;
        SC_HANDLE service = 0;
        SERVICE_STATUS status = {0};
    
        scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
        if (!scmanager)
        {
            goto __Cleanup;
        }
    
        service = ::OpenService(scmanager, name, SERVICE_QUERY_STATUS);
        if (!service)
        {
            goto __Cleanup;
        }
    
        if (QueryServiceStatus(service, &status))
        {
            result = status.dwCurrentState;
        }
    
    __Cleanup:
        if (service)
        {
            ::CloseServiceHandle(service);
        }
        if (scmanager)
        {
            ::CloseServiceHandle(scmanager);
        }
    
        return result;
    }
    
    int NTServiceManager::GetRealStartupType(SERVICE_STARTUP_TYPE type)
    {
        switch (type)
        {
        case SST_AUTO_START:
            {
                return SERVICE_AUTO_START;
            }
        case SST_DEMAND_START:
            {
                return SERVICE_DEMAND_START;
            }
        case SST_DISABLED:
        default:
            {
                return SERVICE_DISABLED;
            }
        }
    }
    
    NTServiceHandler::NTServiceHandler(const std::string &name,
        bool canstop,
        bool canshutdown,
        bool canpausecontinue,
        ServiceTask &service)
        : m_name(name),
        m_service(service)
    {
        memset(&m_status, 0, sizeof(SERVICE_STATUS));
        m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
        m_status.dwCurrentState = SERVICE_START_PENDING;
        m_status.dwWin32ExitCode = NO_ERROR;
        m_status.dwServiceSpecificExitCode = 0;
        m_status.dwCheckPoint = 0;
        m_status.dwWaitHint = 0;
    
        if (canstop)
        {
            m_status.dwControlsAccepted |= SERVICE_ACCEPT_STOP;
        }
        if (canshutdown)
        {
            m_status.dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
        }
        if (canpausecontinue)
        {
            m_status.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
        }
    
        m_status_handle = 0;
    }
    
    NTServiceHandler::~NTServiceHandler()
    {
    }
    
    int NTServiceHandler::Run()
    {
        SERVICE_TABLE_ENTRY st[] =
        {
            {(LPSTR)m_name.c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceMainHandler},
            {NULL, NULL}
        };
    
        return ::StartServiceCtrlDispatcher(st) ? 0 : -1;
    }
    
    void NTServiceHandler::ServiceMainHandler(DWORD argc, LPSTR *argv)
    {
        NTServiceHandler *m_this = GetInstance();
        if (m_this)
        {
            m_this->m_status_handle = RegisterServiceCtrlHandler(m_this->m_name.c_str(), (LPHANDLER_FUNCTION)ServiceCtrlHandler);
            if (!m_this->m_status_handle)
            {
                return;
            }
    
            m_this->NTS_Start(argc, argv);
        }
    }
    
    void NTServiceHandler::ServiceCtrlHandler(DWORD ctrl)
    {
        NTServiceHandler *m_this = GetInstance();
        if (m_this)
        {
            switch (ctrl)
            { 
            case SERVICE_CONTROL_STOP:
                {
                    m_this->NTS_Stop();
                }
                break;
            case SERVICE_CONTROL_PAUSE:
                {
                    m_this->NTS_Pause();
                }
                break;
            case SERVICE_CONTROL_CONTINUE:
                {
                    m_this->NTS_Continue();
                }
                break;
            case SERVICE_CONTROL_SHUTDOWN:
                {
                    m_this->NTS_Shutdown();
                }
                break;
            case SERVICE_CONTROL_INTERROGATE:
            default:
                break;
            }
        }
    }
    
    void NTServiceHandler::NTS_Start(DWORD argc, LPSTR *argv)
    {
        try
        {
            SetServiceStatus(SERVICE_START_PENDING);
            
            if (OnInit(argc, argv) != 0)
            {
                exit(0);
            }
        
            SetServiceStatus(SERVICE_RUNNING);
    
            OnStart();
    
            SetServiceStatus(SERVICE_STOPPED);
        }
        catch (DWORD dwError)
        {
            SetServiceStatus(SERVICE_STOPPED, dwError);
        }
        catch (...)
        {
            SetServiceStatus(SERVICE_STOPPED);
        }
    }
    
    void NTServiceHandler::NTS_Stop()
    {
        DWORD dwOriginalState = m_status.dwCurrentState;
    
        try
        {
            SetServiceStatus(SERVICE_STOP_PENDING);
    
            OnStop();
    
            SetServiceStatus(SERVICE_STOPPED);
        }
        catch (DWORD dwError)
        {
            dwError = 0;
            SetServiceStatus(dwOriginalState);
        }
        catch (...)
        {
            SetServiceStatus(dwOriginalState);
        }
    }
    
    void NTServiceHandler::NTS_Pause()
    {
        try
        {
            SetServiceStatus(SERVICE_PAUSE_PENDING);
    
            OnPause();
    
            SetServiceStatus(SERVICE_PAUSED);
        }
        catch (DWORD dwError)
        {
            dwError = 0;
            SetServiceStatus(SERVICE_RUNNING);
        }
        catch (...)
        {
            SetServiceStatus(SERVICE_RUNNING);
        }
    }
    
    void NTServiceHandler::NTS_Continue()
    {
        try
        {
            SetServiceStatus(SERVICE_CONTINUE_PENDING);
    
            OnContinue();
    
            SetServiceStatus(SERVICE_RUNNING);
        }
        catch (DWORD dwError)
        {
            dwError = 0;
            SetServiceStatus(SERVICE_PAUSED);
        }
        catch (...)
        {
            SetServiceStatus(SERVICE_PAUSED);
        }
    }
    
    void NTServiceHandler::NTS_Shutdown()
    {
        try
        {
            OnShutdown();
    
            SetServiceStatus(SERVICE_STOPPED);
        }
        catch (DWORD dwError)
        {
            dwError = 0;
        }
        catch (...)
        {
        }
    }
    
    void NTServiceHandler::SetServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
    {
        assert(m_status_handle);
    
        static DWORD dwCheckPoint = 0;
    
        m_status.dwCurrentState = dwCurrentState;
        m_status.dwWin32ExitCode = dwWin32ExitCode;
        m_status.dwWaitHint = dwWaitHint;
    
        if (dwCurrentState==SERVICE_RUNNING
            || dwCurrentState==SERVICE_STOPPED)
        {
            m_status.dwCheckPoint = 0;
        }
        else 
        {
            m_status.dwCheckPoint = ++dwCheckPoint;
        }
    
        ::SetServiceStatus(m_status_handle, &m_status);
    }
    
    int NTServiceHandler::OnInit(int argc, char **argv)
    {
        return m_service.OnInit(argc, argv);
    }
    
    void NTServiceHandler::OnStart()
    {
        m_service.OnStart();
    }
    
    void NTServiceHandler::OnStop()
    {
        m_service.OnStop();
    }
    
    void NTServiceHandler::OnPause()
    {
        m_service.OnPause();
    }
    
    void NTServiceHandler::OnContinue()
    {
        m_service.OnContinue();
    }
    
    void NTServiceHandler::OnShutdown()
    {
        m_service.OnShutdown();
    }
    View Code
  • 相关阅读:
    新手第一次联系oracle的碰到的触发器不能创建的问题
    dubbo注册中心占位符无法解析问题(二)
    dubbo注册中心占位符无法解析问题(一)
    .
    Ubuntu16 安装后配置
    TiDB-----使用 TiUP cluster 在单机上模拟生产环境部署步骤
    TiDB 单机安装(在 Linux OS 上部署本地测试环境)
    WPF查找子控件和父控件方法
    Java基础相关
    C++ namespace浅析
  • 原文地址:https://www.cnblogs.com/walker-lc/p/3498284.html
Copyright © 2020-2023  润新知