Window 服务详解

    服务在Window中越来越普及,它有一些不错的优点:自启动、被杀进程后强制自启、在Vista下自动拥有最高权限等。
    下面介绍服务的用法。
    其实编程上服务和一般的EXE几乎没差别,由一个Exe很容易可以改成服务的形式。步骤如下:
    1、改写main函数,下面代码直接使用了服务的框架类,因为服务机制高度统一,所以相关机制直接由框架类来实现,框架类在后面解说。

下面是Main函数:
int _tmain(int argc, _TCHAR* argv[])
{
    CServiceImpl *pServiceImpl = new CServiceImpl;
    _Module.SetImpl(pServiceImpl);

    if (argc < 2)
    {
        _Module.Start(argc, argv);
        return 0;
    }

    // 安装&&反安装
    if (_tcscmp(argv[1], _T("-install")) == 0)
     {
         _Module.Install();
     }
     else if (_tcscmp(argv[1], _T("-uninstall")) == 0)
     {
         _Module.Uninstall();
     }

    return 0;
}

    服务由两种调用方式,一是由服务管理器调用(就是“控制面板”->“管理工具”->“服务”),二是直接调用,所以一边会在直接调用中加上安装和反安装处理。上面代码已经做了这个处理。

    安装代码:
BOOL XServiceModule::Install()
{
    if (IsInstalled())
        return TRUE;
   
    if ( m_pImpl )
    {
        if ( !m_pImpl->Install() )
        {
            cerr << "Install service -- Failed" << endl;
            return FALSE;
        }
    }

    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hSCM == NULL)
    {
        cerr << "Install service -- Couldn't open service manager" << endl;
        return FALSE;
    }
   
    // Get the executable file path
    TCHAR szFilePath[_MAX_PATH];
    ::GetModuleFileName(NULL, szFilePath, _MAX_PATH);
   
    SC_HANDLE hService = ::CreateService(
        hSCM, GetName(), GetDisplayName(),
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
        m_pImpl->IsAutoStart() ? SERVICE_AUTO_START : SERVICE_DEMAND_START,
        SERVICE_ERROR_NORMAL,
        szFilePath, NULL, NULL,
        m_pImpl->GetDependencies(), NULL, NULL);
   
    if (hService == NULL)
    {
        ::CloseServiceHandle(hSCM);
        cerr << "Install service -- Couldn't create service" << endl;
        return FALSE;
    }
   
    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);
    cerr << "Install service -- OK" << endl;
    return TRUE;
}
    可见,调用CreateService向SCManager(服务管理器)注册进去即可。注意CreateService中的参数,服务对应的一些设置由此函数指定,如SERVICE_INTERACTIVE_PROCESS(允许与桌面交互)等。具体可看MSDN或服务管理器中的一些设置。

     反安装:
BOOL XServiceModule::Uninstall()
{
    if (!IsInstalled())
        return TRUE;

    if ( m_pImpl )
    {
        if ( !m_pImpl->Uninstall() )
        {
            cerr << "Uninstall service -- Failed" << endl;
            return FALSE;
        }
    }

    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hSCM == NULL)
    {
        cerr << "Uninstall service -- Couldn't open service manager" << endl;
        return FALSE;
    }

    SC_HANDLE hService = ::OpenService(hSCM, GetName(), SERVICE_STOP | DELETE);
    if (hService == NULL)
    {
        ::CloseServiceHandle(hSCM);
        cerr << "Uninstall service -- Couldn't open service" << endl;
        return FALSE;
    }
   
    SERVICE_STATUS status;
    ::ControlService(hService, SERVICE_CONTROL_STOP, &status);

    BOOL bDelete = ::DeleteService(hService);
   
    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hSCM);

    if (bDelete)
    {
        cerr << "Uninstall service -- OK" << endl;
        return TRUE;
    }

    cerr << "Uninstall service -- Service could not be deleted" << endl;
    return FALSE;
}

    重点关注的是服务的入口函数:
    void XServiceModule::Start(int argc, TCHAR **argv)
{
    static
    SERVICE_TABLE_ENTRY st[] =
    {
        { (LPTSTR)GetName(), ServiceMain },
        { NULL, NULL }
    };
   
    if ( !(::StartServiceCtrlDispatcher(st)) )
    {
        //Error
    }
}

    上面代码指定了服务入口函数为 ServiceMain,下面来看一下此函数:
void XServiceModule::ServiceMain(DWORD dwArgc, LPTSTR*  lpszArgv)
{
    _Module.m_bService = TRUE;

    // Register the control request handler
    m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    m_status.dwWin32ExitCode = 0;
    m_status.dwServiceSpecificExitCode = 0;
    m_status.dwCheckPoint = 0;
    m_status.dwWaitHint = 0;
    m_status.dwCurrentState = SERVICE_START_PENDING;

    m_hServiceStatus = RegisterServiceCtrlHandler(GetName(), _Handler);
    if (m_hServiceStatus == NULL)
    {
        LogEvent(EVENTLOG_ERROR_TYPE, TEXT("Handler not installed"));
        return;
    }
    SetServiceStatus(SERVICE_START_PENDING);

    m_status.dwWin32ExitCode = S_OK;
    m_status.dwCheckPoint = 0;
    m_status.dwWaitHint = 0;

    // When the Run function returns, the service has stopped.
    Run(dwArgc, lpszArgv);
   
    SetServiceStatus(SERVICE_STOPPED);
}
    此函数首先要向服务管理器注册ServiceHandle,此Handle是由服务管理器调用的(它自己另辟线程),注意注册前设置的State的参数,这些参数也直接对应服务的一些设置,如SERVICE_ACCEPT_STOP表示允许在服务管理器中显示“Stop”按钮,用户可以通过此按钮关掉服务。若不允许,则用户看到的“Stop”按钮是灰掉的。

    仓促记下,有空再整理~

你可能感兴趣的:(框架,manager,service,null,Access,Path)