Research on service under windows

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

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325393627&siteId=291194637
Recommended