1. 程式人生 > >WIndows以服務形式啟動程式

WIndows以服務形式啟動程式

//*.h
#pragma once

#ifdef WIN32
#include <windows.h>
#include <strsafe.h>


#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; }