[C++] a Full Featured CAtlServiceModuleT implementation...

I had to do some maintenance on a Windows ® service and found that you can use an ATL service as a windows service very well without all the overhead.

 

There are some samples on the internet, but they stop where I wanted to continue. That is, run UI-less services for instance, a job that could be done through a task scheduled-job but better be done through a service?

 

b.t.w. for the ones interested in a minimal windows service and who feel a sick inclination J writing the smallest EXE possible, they should use  a plain C implementation provided by  Microsoft’s ® Platform SDK located at [Platform SDK folder]\Samples\WinBase\Service and they should not use MS VC 8 but 4 or so...

 

Note that the grey highlighted code, is my code, the normal colored code is left over of what the MS Visual Studio created for you through the wizard. In addition, I’ve snipped all trace & debugging code.

The Visual Studio 2005 wizard creates an EXE that is suitable both as COM service (DCOM) and as windows service. You can guess a lot of overhead and unneeded lines.

 

This service does not perform anything, keep in mind it is a template for a 'scheduled' task-service, a batch for instance. Your code comes within DoDBMSJob...

 

// Service_Template.cpp : Implementation of WinMain

 

#include "stdafx.h"

#include "resource.h"

 

#include "Service_Template.h"

#pragma warning(disable: 4482) // nonstandard extension used: 'enum CServiceStatus' used in qualified name

 

[v1_enum] //32 bit rulez

enum CServiceStatus

{

      run = 0,

      pauze=1,

      stop = 2,

      shutmedown=3

};

class CService_Module : public CAtlServiceModuleT< CService_Module, IDS_SERVICENAME >

{

private:

      // this flag in milliseconds, tells us how often

      // is checked for tasks

      DWORD m_iPollTime;

      HANDLE m_ThreadHandle; // eventually use CHandle

      HANDLE  m_hServerStopEvent;

      bool connDone;

      CServiceStatus m_ServiceStatus ;

      bool stopNow;

public :

      ~CService_Module() throw()

      {

            if (m_ThreadHandle != NULL)

                  CloseHandle(m_ThreadHandle);

            if (m_hServerStopEvent != NULL)

                  CloseHandle(m_hServerStopEvent);

      }

      CService_Module()  throw():   m_iPollTime(10), m_ThreadHandle(NULL), m_hServerStopEvent(NULL),

            stopNow(false)

      {

            m_ServiceStatus =CServiceStatus::run;

            //m_dwTimeOut = 60000; // one minute

 

           

      }

      // we can’t skip this! Leave as is created by wizard

      DECLARE_REGISTRY_APPID_RESOURCEID(IDR_GARBAGE_COLLECT, "{44DE094D-9AE1-5A56-A1A7-A20F9EAE0F21}")

 

      HRESULT InitializeSecurity() throw()

      {

// we don’t need this here

            return S_OK;

      }

 

      void OnPauze() throw()

      {

            m_ServiceStatus = CServiceStatus::pauze;

            __super::OnPause();

            if ( m_hServerStopEvent != NULL)

                  SetEvent(m_hServerStopEvent);

           

      }

      void OnStop() throw()

      {

            __super::OnStop();

            m_ServiceStatus =CServiceStatus::stop;

            if ( m_hServerStopEvent != NULL)

            {

                  stopNow= true;

                  // be sure not to kill the thread & process

                  // before it nicely ends

                  // otherwise, our pointers will ‘Release()’ while

                  // the instance has been killed already, a common bug!

                  SetEvent(m_hServerStopEvent);

                  DWORD tc = GetTickCount();

                  while(m_hServerStopEvent != NULL || GetTickCount() - tc > 20000) // max 20 seconds wait

                        Sleep(10);

            }

      }

 

      void OnContinue( ) throw( )

      {

            __super::OnContinue();

            m_ServiceStatus =CServiceStatus::run;

            if ( m_hServerStopEvent != NULL)

                  SetEvent(m_hServerStopEvent);

      }

 

      void OnShutDown() throw()

      {    

            //__super::OnShutDown();

            m_ServiceStatus =CServiceStatus::pauze;

            if ( m_hServ

blog comments powered by Disqus