/windows_service_base.h
/*************************
*
*Date :2018-03-03
*Author :Yoohoo Niu
*Desc :windows service running on background.
* copyright(c) Yoohoo.Niu
**************************/
#include <windows.h>
#include <assert.h>
class windows_service_base
{
public:
windows_service_base(const std::string service_name, bool is_can_stop = true,
bool is_can_shutdown = true, bool is_can_pause_continue = false);
virtual ~windows_service_base();
/*load the service app*/
static bool run(windows_service_base& service_instance);
protected:
/*when implemented in a derived class,make it strong,so it's that a interface.*/
virtual void on_start(int argc, char** argv) {};
virtual void on_stop() {};
virtual void on_pause() {};
virtual void on_continue() {};
virtual void on_shutdown() {};
private:
static void WINAPI service_main(int argc, char** argv);
static void WINAPI service_ctrl(int request);
void set_service_status(DWORD status);
void start(int argc, char** argv);
void stop();
void pause();
void continu();
void shutdown();
private:
static windows_service_base* __service;
std::string __service_name;
SERVICE_STATUS __service_status;
SERVICE_STATUS_HANDLE __service_status_handle;
};
//windows_service_base.cpp
#include <iostream>
#include "windows_service_base.h"
using namespace std;
windows_service_base* windows_service_base::__service = NULL;
windows_service_base::windows_service_base(std::string service_name, bool is_can_stop,
bool is_can_shutdown, bool is_can_pause_continue):__service_name(service_name),
__service_status_handle(NULL)
{
__service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
__service_status.dwCurrentState = SERVICE_START_PENDING;
DWORD dwControlsAccepted = 0;
if (is_can_stop)
{
dwControlsAccepted |= SERVICE_ACCEPT_STOP;
}
if (is_can_shutdown)
{
dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
}
if (is_can_pause_continue)
{
dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
}
__service_status.dwControlsAccepted = dwControlsAccepted;
__service_status.dwWin32ExitCode = 0;
__service_status.dwServiceSpecificExitCode = 0;
__service_status.dwCheckPoint = 0;
__service_status.dwWaitHint = 0;
}
windows_service_base::~windows_service_base()
{
}
bool windows_service_base::run(windows_service_base& service_instance)
{
__service = &service_instance;
char service_name[512] = {0};
memcpy(service_name, __service->__service_name.c_str(), 512);
SERVICE_TABLE_ENTRYA service_table[] =
{
{ service_name, (LPSERVICE_MAIN_FUNCTIONA)__service->service_main },
{ NULL, NULL }
};
return StartServiceCtrlDispatcherA(service_table);
}
void windows_service_base::service_main(int argc, char** argv)
{
assert(__service != NULL);
__service->__service_status_handle = RegisterServiceCtrlHandlerA(__service->__service_name.c_str(),(LPHANDLER_FUNCTION)__service->service_ctrl);
if (__service->__service_status_handle == NULL)
{
throw GetLastError();
}
__service->start(argc, argv);
}
void windows_service_base::service_ctrl(int request)
{
switch (request)
{
case SERVICE_CONTROL_STOP:
__service->stop();
break;
case SERVICE_CONTROL_PAUSE:
__service->pause();
break;
case SERVICE_CONTROL_CONTINUE:
__service->continu();
break;
case SERVICE_CONTROL_SHUTDOWN:
__service->shutdown();
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default: break;
}
}
void windows_service_base::set_service_status(DWORD status)
{
__service_status.dwCurrentState = status;
SetServiceStatus(__service_status_handle, &__service_status);
}
void windows_service_base::start(int argc, char** argv)
{
try
{
set_service_status(SERVICE_START_PENDING);
on_start(argc, argv);
set_service_status(SERVICE_RUNNING);
}
catch (DWORD err)
{
set_service_status(SERVICE_STOPPED);
//writelog
}
catch (...)
{
set_service_status(SERVICE_STOPPED);
//writelog
}
}
void windows_service_base::stop()
{
DWORD last_status = __service_status.dwCurrentState;
try
{
set_service_status(SERVICE_STOP_PENDING);
on_stop();
set_service_status(SERVICE_STOPPED);
}
catch (DWORD err)
{
set_service_status(last_status);
//writelog
}
catch (...)
{
set_service_status(last_status);
//writelog
}
}
void windows_service_base::pause()
{
DWORD last_status = __service_status.dwCurrentState;
try
{
set_service_status(SERVICE_PAUSE_PENDING);
on_stop();
set_service_status(SERVICE_PAUSED);
}
catch (DWORD err)
{
set_service_status(last_status);
//writelog
}
catch (...)
{
set_service_status(last_status);
//writelog
}
}
void windows_service_base::continu()
{
DWORD last_status = __service_status.dwCurrentState;
try
{
set_service_status(SERVICE_CONTINUE_PENDING);
on_stop();
set_service_status(SERVICE_RUNNING);
}
catch (DWORD err)
{
set_service_status(last_status);
//writelog
}
catch (...)
{
set_service_status(last_status);
//writelog
}
}
void windows_service_base::shutdown()
{
try
{
on_stop();
set_service_status(SERVICE_STOPPED);
}
catch (DWORD err)
{
//writelog
}
catch (...)
{
//writelog
}
}
class swallow_service : public windows_service_base
{
public:
using windows_service_base::windows_service_base;
protected:
void on_start(int argc, char**argv)
{
log_stream << "start running swallow service...." << endl;
}
};
int main()
{
windows_service_base base("base");
swallow_service swallow("swallow");
//windows_service_base::run(base);
windows_service_base::run(swallow);
return 0;
}