WIndows以服務形式啟動程式
阿新 • • 發佈:2019-02-19
//*.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;
}