WIndows以服务形式启动程序

//*.h
#pragma once

#ifdef WIN32
#include 
#include 


#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "strsafe.lib")


#define SVCNAME TEXT("wind.cosmos.dbsync.server")
#define SVCDISPLAYNAME TEXT("wind.cosmos.dbsync.server")
#define SVC_ERROR                        ((DWORD)0xC0020001L)

SERVICE_STATUS          gSvcStatus;
SERVICE_STATUS_HANDLE   gSvcStatusHandle;
HANDLE                  ghSvcStopEvent = NULL;

typedef VOID(*REAL_FUNCTION)(DWORD dwArgc, LPTSTR *lpszArgv);

static VOID SvcInit(DWORD dwArgc, LPTSTR *lpszArgv);
static  VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
static VOID WINAPI SvcCtrlHandler(DWORD dwCtrl);
static VOID SvcReportEvent(LPTSTR szFunction);

REAL_FUNCTION  _realFunc = NULL;

void Print(const char* log)
{
    static ofstream out("D:\\test.txt");
    out << log << endl;
}

void serviceInstall() {
    SC_HANDLE schSCManager;
    SC_HANDLE schService;
    TCHAR szPath[MAX_PATH];

    if (!GetModuleFileName(NULL, szPath, MAX_PATH))
    {
        printf("Cannot install service (%d)\n", GetLastError());
        return;
    }
    // Get a handle to the SCM database. 
    schSCManager = OpenSCManager(
        NULL,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 

    if (NULL == schSCManager)
    {
        printf("OpenSCManager failed (%d)\n", GetLastError());
        return;
    }
    // Create the service
    schService = CreateService(
        schSCManager,              // SCM database 
        SVCNAME,                   // name of service 
        SVCDISPLAYNAME,                   // service name to display 
        SERVICE_ALL_ACCESS,        // desired access 
        SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // service type 
        SERVICE_AUTO_START,      // start type 
        SERVICE_ERROR_NORMAL,      // error control type 
        szPath,                    // path to service's binary 
        NULL,                      // no load ordering group 
        NULL,                      // no tag identifier 
        NULL,                      // no dependencies 
        NULL,                      // LocalSystem account 
        NULL);                     // no password 

    if (schService == NULL)
    {
        //printf("CreateService failed (%d)\n", GetLastError());
        CloseServiceHandle(schSCManager);
        wchar_t errInfo[256];
        _snwprintf(errInfo, 256, (const wchar_t*)"Windows服务安装失败(%d)\n", GetLastError());
        MessageBox(NULL, errInfo, TEXT("失败"), MB_ICONERROR | MB_OK);
        return;
    }
    else {
        /**
        typedef struct _SERVICE_DESCRIPTION {  LPTSTR lpDescription;
        } SERVICE_DESCRIPTION,  *LPSERVICE_DESCRIPTION;
        */
        SERVICE_DESCRIPTION service_desc;
        service_desc.lpDescription = TEXT("Cosmos数据库同步服务端.");
        ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &service_desc);
        /*修改故障重启配置*/
        /**
        typedef struct _SERVICE_FAILURE_ACTIONS {  DWORD dwResetPeriod;  LPTSTR lpRebootMsg;  LPTSTR lpCommand;  DWORD cActions;  SC_ACTION* lpsaActions;
        } SERVICE_FAILURE_ACTIONS,  *LPSERVICE_FAILURE_ACTIONS;

        typedef struct _SC_ACTION {  SC_ACTION_TYPE Type;  DWORD Delay;
        } SC_ACTION,  *LPSC_ACTION;

        */
        SERVICE_FAILURE_ACTIONS  failure_actions;
        failure_actions.dwResetPeriod = 60 * 60;
        failure_actions.lpRebootMsg = TEXT("wind.cosmos.dbsync.server服务发生过异常崩溃");
        failure_actions.lpCommand = NULL;
        failure_actions.cActions = 3;
        SC_ACTION* actions = new SC_ACTION[3];
        actions[0].Type = SC_ACTION_RESTART;
        actions[0].Delay = 1000 * 3;
        actions[1].Type = SC_ACTION_RESTART;
        actions[1].Delay = 1000 * 3;
        actions[2].Type = SC_ACTION_RESTART;
        actions[2].Delay = 1000 * 3;
        failure_actions.lpsaActions = actions;

        ChangeServiceConfig2(schService, SERVICE_CONFIG_FAILURE_ACTIONS, &failure_actions);
        delete[] actions;

        /**
        BOOL WINAPI StartService(
        __in          SC_HANDLE hService,
        __in          DWORD dwNumServiceArgs,
        __in          LPCTSTR* lpServiceArgVectors
        );

        */
        /*服务安装完成后自动启动本服务*/
        BOOL ret = StartService(schService, 0, NULL);
        if (!ret)
        {
            DWORD err = GetLastError();
            char chErr[64];
            sprintf(chErr, "GetLastError = %d", err);
            Print("StartService failed");
            Print(chErr);
        }
        else
        {
            Print("StartService Success");
        }
        MessageBox(NULL,TEXT("服务(wind.cosmos.dbsync.server)安装成功"),TEXT("Succ"),MB_OK);
        CloseServiceHandle(schService);
        CloseServiceHandle(schSCManager);
        return;
    }
}

void serviceUninstall() {
    SC_HANDLE schSCManager;
    SC_HANDLE schService;
    TCHAR szPath[MAX_PATH];

    if (!GetModuleFileName(NULL, szPath, MAX_PATH))
    {
        printf("Cannot install service (%d)\n", GetLastError());
        return;
    }
    // Get a handle to the SCM database. 
    schSCManager = OpenSCManager(
        NULL,                    // local computer
        NULL,                    // ServicesActive database 
        SC_MANAGER_ALL_ACCESS);  // full access rights 

    if (NULL == schSCManager)
    {
        printf("OpenSCManager failed (%d)\n", GetLastError());
        return;
    }
    schService = OpenService(schSCManager, SVCNAME, SC_MANAGER_ALL_ACCESS);
    if (schService == NULL) {
        CloseServiceHandle(schSCManager);
        wchar_t errInfo[256];
        _snwprintf(errInfo, 256, (const wchar_t*)"打开Windows服务(wind.cosmos.dbsync.server)失败.(%d)\n", GetLastError());
        MessageBox(NULL, errInfo, TEXT("失败"), MB_ICONERROR | MB_OK);
        return;
    }
    else {
        if (DeleteService(schService)) {
            MessageBox(NULL, TEXT("服务(wind.cosmos.dbsync.server)卸载成功"), TEXT("Succ"), MB_OK);
        }
        else {
            wchar_t errInfo[256];
            _snwprintf(errInfo, 256, (const wchar_t*)"卸载Windows服务(wind.cosmos.dbsync.server)失败.(%d)\n", GetLastError());
            MessageBox(NULL, errInfo, TEXT("失败"), MB_ICONERROR | MB_OK);
        }
        CloseServiceHandle(schService);
        CloseServiceHandle(schSCManager);       
    }
}

VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
    // Register the handler function for the service
    gSvcStatusHandle = RegisterServiceCtrlHandler(
        SVCNAME,
        SvcCtrlHandler);
    if (!gSvcStatusHandle)
    {
        SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
        return;
    }
    // These SERVICE_STATUS members remain as set here
    gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    gSvcStatus.dwServiceSpecificExitCode = 0;
    // Report initial status to the SCM
    ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
    // Perform service-specific initialization and work.
    SvcInit(dwArgc, lpszArgv);
}

static VOID SvcInit(DWORD dwArgc, LPTSTR *lpszArgv)
{
    // Create an event. The control handler function, SvcCtrlHandler,
    // signals this event when it receives the stop control code.
    ghSvcStopEvent = CreateEvent(
        NULL,    // default security attributes
        TRUE,    // manual reset event
        FALSE,   // not signaled
        NULL);   // no name

    if (ghSvcStopEvent == NULL)
    {
        ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
        return;
    }

    //start the real function
    if (_realFunc != NULL) {
        _realFunc(dwArgc, lpszArgv);
    }
    // Report running status when initialization is complete.
    ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
    // TO_DO: Perform work until service stops.

    while (1)
    {
        // Check whether to stop the service.
        WaitForSingleObject(ghSvcStopEvent, INFINITE);
        ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
        return;
    }
}

static  VOID ReportSvcStatus(DWORD dwCurrentState,DWORD dwWin32ExitCode,DWORD dwWaitHint)
{
    static DWORD dwCheckPoint = 1;
    // Fill in the SERVICE_STATUS structure.
    gSvcStatus.dwCurrentState = dwCurrentState;
    gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
    gSvcStatus.dwWaitHint = dwWaitHint;

    if (dwCurrentState == SERVICE_START_PENDING)
        gSvcStatus.dwControlsAccepted = 0;
    else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

    if ((dwCurrentState == SERVICE_RUNNING) ||
        (dwCurrentState == SERVICE_STOPPED))
        gSvcStatus.dwCheckPoint = 0;
    else gSvcStatus.dwCheckPoint = dwCheckPoint++;

    // Report the status of the service to the SCM.
    SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
}

static VOID WINAPI SvcCtrlHandler(DWORD dwCtrl)
{
    switch (dwCtrl)
    {
    case SERVICE_CONTROL_STOP:
        ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
        // Signal the service to stop.
        SetEvent(ghSvcStopEvent);
        ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
        return;
    case SERVICE_CONTROL_INTERROGATE:
        break;
    default:
        break;
    }

}

static VOID SvcReportEvent(LPTSTR szFunction)
{
    HANDLE hEventSource;
    LPCTSTR lpszStrings[2];
    TCHAR Buffer[80];
    hEventSource = RegisterEventSource(NULL, SVCNAME);
    if (NULL != hEventSource)
    {
        StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());

        lpszStrings[0] = SVCNAME;
        lpszStrings[1] = Buffer;

        ReportEvent(hEventSource,        // event log handle
            EVENTLOG_ERROR_TYPE, // event type
            0,                   // event category
            SVC_ERROR,           // event identifier
            NULL,                // no security identifier
            2,                   // size of lpszStrings array
            0,                   // no binary data
            lpszStrings,         // array of strings
            NULL);               // no binary data

        DeregisterEventSource(hEventSource);
    }
}

#endif

//main.cpp
void runService();

VOID service_start_func(DWORD dwArgc, LPTSTR *lpszArgv)
{
    Print("service_start_func");
    runService();
}

bool runAsService(int argc, char** argv) {
    Print("runAsService");
    _realFunc = service_start_func;
    /*服务管理器中启动,首先进入本函数*/
    //SvcReportEvent(TEXT("runAsService called"));
    SERVICE_TABLE_ENTRY DispatchTable[] =
    {
        { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
        { NULL, NULL }
    };

    // This call returns when the service has stopped. 
    // The process should simply terminate when the call returns.
    if (!StartServiceCtrlDispatcher(DispatchTable))
    {
        //SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
        MessageBox(NULL, TEXT("Windows服务.\n  命令行运行请带debug参数\n  安装服务请带install参数\n  卸载服务请带uninstall参数"), TEXT("警告"), MB_OK);
        return false;
    }
    else {
        return true;
    }
}

int main(int argc, char** argv)
{
    //启动服务
    {
        int runningMode = 0;
        if (argc == 1)
        {
            runningMode = 4;
        }
        else
        {
            if (_stricmp(argv[1], "install") == 0) {
                runningMode = 1;
            }
            else if (_stricmp(argv[1], "uninstall") == 0) {
                runningMode = 2;
            }
            else if (_stricmp(argv[1], "debug") == 0) {
                runningMode = 3;
            }
        }

        switch (runningMode) {
        case 1:
            {
                serviceInstall();
                return 0;
            }
        case 2:
            {
                serviceUninstall();
                return 0;
            }
        case 3:
            {
                break;
            }
        case 4:
            runAsService(argc, argv);
            //runService();
            return 0;
        default:
            return -1;
        }
    }
    return 0;
}

你可能感兴趣的:(C/C++)