The win::service class abstracts all the Windows API calls neccessary to implement a service and/or to control the service.
class win::service {
public:
enum flags {
can_be_paused = 0x01,
receive_device_events = 0x02,
receive_power_events = 0x04,
receive_hardware_events = 0x08,
receive_session_events = 0x10,
};
protected:
const bool & as_console;
protected:
explicit service (const std::string &,
flags = static_cast <flags> (0));
virtual ~service () throw ();
void step () throw ();
private:
// Interface for implementation of services
virtual void main () = 0;
virtual bool on_initialize (void *);
virtual void on_pause ();
virtual void on_resume ();
virtual void on_stop ();
virtual void on_shutdown ();
virtual bool on_command (unsigned int);
virtual void on_device_event (unsigned int, void *);
virtual bool on_power_event (unsigned int);
virtual void on_session_change (unsigned int, unsigned int);
virtual bool on_hardware_change (unsigned int);
private:
service (const service &);
service * operator = (const service &);
public:
// Interface for controlling the service
void run () throw ();
void install (const std::string &) throw (ext::runtime_error);
void remove () throw (ext::runtime_error);
void set_description (const char *) throw (ext::runtime_error);
void set_description (const wchar_t *) throw (ext::runtime_error);
void set_autostart (bool) throw (ext::runtime_error);
void start () throw (ext::runtime_error);
void stop () throw (ext::runtime_error);
bool command (unsigned int) throw (ext::runtime_error);
};
The main should exit only after asked to do so, e.g. by having the on_stop invoked. If main member function exits, the service is stopped without calling the on_stop member function. Any uncaught exception will result in premature stop of the service with the ERROR_EXCEPTION_IN_SERVICE error code. As an exception, the std::bad_alloc exception will result in stop with the ERROR_NOT_ENOUGH_MEMORY error.
If the run member function is called when the process is not being executed by service manager, e.g. not being run as service but started by user (for example), the main member function is still called, but following constrains apply:
An implementation of this member function is required even for service control-only applications although it may (and should) remain empty for this purpose.
To use the win::service a concrete service class must be derived from win::service.
For both uses, the actual service process and service-controller process, the win::service base must be constructed with the same flags. Otherwise the misconfigured features may not be available or may not work properly. The behavior in this case is intentionally left undefined so it can change in future versions.
The win::service object cannot be copied.
In order to use win::service, the following files need to be included into the project:
#include <ext/win>
#include <csignal>
class service_type : public win::service {
private:
static void signal_handler (int);
static const char * name;
private:
volatile bool quit;
private:
virtual void on_stop () {
this->quit = true;
};
virtual void main () {
while (!this->quit) {
// ...
};
return;;
};
public:
service_type ();
} service;
void service_type::signal_handler (int) {
service.quit = true;
};
service_type::service_type ()
: win::service (name),
quit (false) {
std::signal (SIGINT, &service_type::signal_handler);
std::signal (SIGTERM, &service_type::signal_handler);
std::signal (SIGBREAK, &service_type::signal_handler);
};
const char * service_type::name = "Test Service";
int main () {
service.run ();
return 0;
};
The example above shows also how to gracefuly terminate the process on break signals (Ctrl+C, ...) when not running as a service. Also note that second such signal forces the termination of the process anyway.
Note that to inherit in order to reuse (as you need to in order to use win::service) is not a best practice. Prefer to inherit in order to be reused.
The win::service always accepts a shutdown and stop commands by design.
See MSDN (Platform SDK) for more details regarding Windows Services.
[index]