A Class For Building An NT Service

Building a Service


Changes to revision 2


NT Service Using MFC


Download

Ever tried to write an NT service ? :->


One of my very latest projects was to develop a CORBA server running

as an NT service. Since one of my next projects will be an NT service too,

I let my brain work a little harder to get it ready for as many programs

as needed. The result of this was the CNTService class, that I want to

share with the codegurus 🙂


With this class it is very simple to create an NT service. Just derive

your own class and override the “Run()” and “Stop()” pure virtual members.

All of the hard bits are done by the class.

There are several virtuals to overload (multi-threading, pausable services

and more).

The class accepts a set of command-line parameters. For instance you

can pass the -d switch to let it run as a console process. This makes debugging

much easier.


Furthermore the class has abilities to (de)install the service. This

is usually a command-line switch too (but one can customize this :-).

CNTService compiles with and without UNICODE settings.


 

Building a Service

Now lets have a closer look at how you can build your own service.


Follow these steps (assuming you’re using VC++ 5.0):

  1. create a new project workspace of type “console application”

  2. copy the files of the NTService package into the directory of your new

    project

  3. insert “NTService.cpp” and “NTServiceEventLogMsg.mc” into your project

  4. open the Project->Settings … dialog and fill it out. See the image

    below. It says more than I could write 🙂

  5. compile the file “NTServiceEventLogMsg.mc”. This will produce the files

    “NTServiceEventLogMsg.h” and “NTServiceEventLogMsg.rc”.

  6. insert the generated RC file into your project.

  7. derive your own class from CNTService and override at least the two methods

    “Run()” and “Stop()”

  8. write a simple “main()” to start up your program’s functionality 🙂 (You

    can use the sample project for a good starting point)

  9. Once your project compiles without errors, you can immediately start it.

    To do so, you should open the Project->Settings … dialog once

    again. Select All Configurations and than check the line with the

    name of your project. Activate the tab Debug and insert the -d

    switch in the field Program arguments:


  10. Now you should be able to run and debug your service as a console program.

    You can use either Ctrl-C or Ctrl-Break to stop the service (that would

    simulate a Stop request from the service control manager)


How to fill out the settings of the file NTServiceEventLogMsg.mc

Now lets try to start the service as a real NT service (assuming you

use the sample project):

  1. Log on as an administrator, if your account isn’t in the administrators

    group (this will make life somewhat easier)

  2. Start the program with the switch -i. This will install your service.

  3. If the last step completes successfully, you can open the control panel

    and start the Services applet. Search for the display name of your

    service and select it (Very Simple Service if you try the sample).

  4. Press the Startup … button. Have a look at the Log On As:

    box. For now you can let the check at System Account. If you try

    the sample, make sure you check the Interact With The Desktop box.

    This is necessary, since the sample uses the MessageBox() function (which

    interacts with the desktop). If you don’t check this box, the sample will

    not run properly and will hang up itself; thus you’re unable to stop the

    service again ! With a little bit of experience one can enhance the sample,

    so that it will install the service with this box already checked, but

    I wanted to keep the sample as simple as possible, so I leave it to you

    to implement that. 🙂

The sample project implements a very simple service. The derived class

(declaration and implementation) and the main() function are all in the

same file (main.cpp). This file is less than 100 lines long (strip off

all the comments and it will fit on one page of printing !)


The service only pops up a message-box every 10 seconds.

For more information have a look at CNTService.h and – of course – the

sample. I think it is well commented (let me

know, if you don’t think so)


 

Changes to revision 2

  • Added two more switches to handle command line arguments: -e will force

    a running service to stop (corresponding method in this class: virtual

    BOOL EndService();) and -s will force the service to start, if it is not

    already running (method: virtual BOOL StartupService())

  • Todd C. Wilson added support for

    Win95. This enables you to create a service like application for Windows

    95 (a socalled “Faceless Application”). Like a service, such an application

    will be started automatically by the system and will survive a user’s logoff.

    My own experience with this kind of applications are not very great: Yes

    I could logoff, but the system hung when I tried to logon again. Furthermore

    BoundsChecker 5 (yes – I always test my software with this great tool 🙂

    said, that the following sentence returns an invalid pointer (exactly “returned

    pointer is not a pointer to a function”):


  •  typedef DWORD (WINAPI *fp_RegServProc)(DWORD

    dwProcessId,DWORD dwType);


     fp_RegServProc fncptr=NULL;


    // …


    HMODULE hModule = ::GetModuleHandle(TEXT(“kernel32.dll”));


    fncptr=(fp_RegServProc)::GetProcAddress(hModule,

    “RegisterServiceProcess”);


    if (fncptr!=NULL)


        (*fncptr)(0, RSP_SIMPLE_SERVICE);


    If the last line is reached, BoundsChecker warns,

    that fncptr

    does not point to a function. However, the sample program continues execution

    without an (serious) error.


    You should keep this problem in mind, if you

    plan to develop a faceless application for windows 95.


    The sample project offers a configuration “Win32

    Win95 Debug”, that you can use to try this new feature.


     


     

NTService Using MFC

Microsoft recommends to write an NT service as a console application .

However, it is possible to write such a service using MFC, too. To do so,

it isn’t necessary to create an  MFC Wizard Application (although

it is possible of course, but you have to


remove a lot of code, because normally you don’t need the doc/view

concept), but a simple Win32 application is just enough. Make sure you

select Using MFC in a shared DLL from the General tab of

the Settings dialog of your project. Furthermore, you have to select

Multithreaded DLL / Debug Multithreaded DLL in the C/C++

tab, section Code Generation field Use run-time Library.


If you’re using a precompiled header, make sure you don’t  #define

VC_EXTRALEAN, because the MFC based service needs parts of the “rarely

used stuff”, that this macro would exclude from the windows headers!


I’ve added a new project MFCService as part of the workspace

of the sample service to demonstrate this. Just try it out and/or use it

as a starting point for a more complex service. The service (installation/removal

etc). works exactly as described in the sections above.

CNTService consists of three files:


NTService.h


NTService.cpp


NTServiceEventLogMsg.mc


Download Source 14KB


Download Sample Project

23KB

Note that the file NTServiceEventLogMsg.mc  is copyrighted by Telic

Software International B.V. Many thanks to Telic for providing it in the

public domain!

Date Last Updated: February 5, 1999

More by Author

Must Read