Writing a Service Program

Environment: Visual C++6 SP5, Windows 2000/XP

Introduction

A few weeks ago, I was trying to make my own server application into a service without much knowledge about how to do it. Now, I know more about services and would like to share my knowledge in this article.

Services are processes that can be auto started when the system boots, and can be left them running while the system is on. For example, system services are services such as an Event log that logs messages issued by Windows-based programs and components to be viewed in Event Viewer. Services are similar to UNIX's daemons.

A Windows service applet can be found in Control Panel > Administrator Tools > Services. Any new services installation creates an entry in this applet and in the Registry (HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services), so that the system knows about it each time it boots.

Every service must be able to respond to a set of standard events that the services applet can pass to it. These events are shown in the window service as buttons:

  • START: Starts the service if it is a manual start service or it is stopped.
  • STOP: Stops the service.
  • PAUSE: Suspends the service temporarily.
  • CONTINUE: Resumes the suspended service.

All services are managed under a system called the Service Control Manager. It maintains the list of known services in the Registry and starts them at boot time or when requested.

A program that acts as a service is a normal EXE file, but it must meet special requirements so that it interfaces properly with the Service Control Manager (SCM). The requirements follow:

  1. EXE must have a normal main or WinMain function. Call the StartServiceCrtlDispatcher function to register the EXE with the SCM and give the SCM a pointer to the ServiceMain function.
  2. void main(int argc, char *argv[])
    {
      SERVICE_TABLE_ENTRY serviceTable[] =
      {
        { ServiceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
          { NULL, NULL}
      };
      BOOL success;
    
      if(argc == 2)
        //..check arguments
      else
      {
        //register with SCM
        success = StartServiceCtrlDispatcher(serviceTable);
        if (!success)
          ErrorHandler("StartServiceCtrlDispatcher",
                        GetLastError());
      }
    }
    
  3. SCM will call the ServiceMain function when it wants to start the service. The ServiceMain should immediately call the RegisterServiceCtrlHandler function to register a Handler function with SCM.
  4. void ServiceMain(DWORD argc, LPTSTR *argv)
    {
      BOOL success;
    
      //immediately call registration function
      serviceStatusHandle =
             RegisterServiceCtrlHandler(ServiceName,
             (LPHANDLER_FUNCTION)ServiceCtrlHandler);
    
      //notify SCM
      //create termination event
      terminateEvent = CreateEvent (0, TRUE, FALSE, 0);
      .
      .
      //notify SCM
      .
      .
      //check for startup parameter
      //start service
      //notify SCM service is runnning
      SendStatusToSCM(SERVICE_RUNNING, NO_ERROR, 0 , 0, 0);
    
      //wait for stop signal and then terminate
      WaitForSingleObject(terminateEvent, INFINITE);
    
      terminate(0);
    }
    
  5. The Handler function contains switch statements that parse control requests received from the SCM.
  6. void ServiceCtrlHandler(DWORD controlCode)
    {
      DWORD currentState = 0;
      BOOL success;
    
      switch(controlCode)
      {
        // START = ServiceMain()
    
        // STOP
        case SERVICE_CONTROL_STOP:
          currentState = SERVICE_STOP_PENDING;
          //notify SCM
          SendStatusToSCM(SERVICE_STOP_PENDING,
            NO_ERROR,
            0,
            1,
            5000);
          //stop service
          StopService();
          return;
    
        // PAUSE
        case SERVICE_CONTROL_PAUSE:
          if (runningService && !pauseService)
          {
            //notify SCM
            success = SendStatusToSCM(
              SERVICE_PAUSE_PENDING,
              NO_ERROR,
              0,
              1,
              1000);
    
            PauseService();
            currentState = SERVICE_PAUSED;
          }
          break;
    
        // RESUME
        case SERVICE_CONTROL_CONTINUE:
          if (runningService && pauseService)
          {
            //notify SCM
            success = SendStatusToSCM(
              SERVICE_CONTINUE_PENDING,
              NO_ERROR,
              0,
              1,
              1000);
    
            ResumeService();
            currentState = SERVICE_RUNNING;
          }
          break;
    
        // UPDATE
        case SERVICE_CONTROL_INTERROGATE:
          //update status out of switch()
          break;
    
        case SERVICE_CONTROL_SHUTDOWN:
          //do nothing
          return;
        default:
          break;
      }
      //notify SCM current state
      SendStatusToSCM(currentState, NO_ERROR, 0, 0, 0);
    }
    
  7. When you create an EXE that contains that main, ServiceMain, and Handler functions, as well as a function that contains the thread for the service itself, you will have a complete service program.

Template for the Service Program

The accompanying .cpp file is a template for the service program, service control program (RUN, STOP, PAUSE, CONTINUE), and also the configuration program in the sense that it can install or remove the EXE itself using command.

Usage

  1. Add service.cpp to the project workspace.
  2. Change the ServiceName under the global variable to the desired name.
  3. Add your function into ServiceThread().
  4. DONE!

To Install

  1. Use command prompt.
  2. Locate the EXE.
  3. Type <programname> -i to install
    Type <programname> -u to uninstall
    Type <programname> -r to run
    Type <programname> -s to stop
    Type <programname> -p to pause
    Type <programname> -c to continue
    Type <programname> help

Downloads

Download source - 6 Kb


Comments

  • problem in pause

    Posted by samira on 08/14/2012 03:18am

    hi thanks for ur nice post! ive developed a service like u but ihave a problem in pause the service! my service work when i pause it and its get changed to pause but it dosnt sleep! it mean the code in its service main continiue running!!!! what can i do because this section run in operating system side!!!

    Reply
  • invalid current state 0

    Posted by chuck59 on 09/20/2005 08:58am

    I modified your code to integrate it into my application. Now, I've a DLL which fetches and displays status of all services. Every other service reports their correct current except this one; following was logged into the Event Manager...
    
    The  service has reported an invalid current state 0.
    
    Event Type:	Error
    Event Source:	Service Control Manager
    Event Category:	None
    Event ID:	7016
    Date:		20-Sep-05
    Time:		17:40:26
    User:		N/A
    Computer:	
    Description:
    The PServ3 service has reported an invalid current state 0.
    
    For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
    
    Waiting for your reply.

    Reply
  • Very Good

    Posted by anantwakode on 09/19/2005 05:22am

    Its nice artical for begineer to understand Service app

    Reply
  • How to build a project?

    Posted by Tinoky on 05/09/2005 04:09pm

    It's exactly what I'm searching for. But since I never built any project without using the Application Wizard, I don't know how to build this service. Can anybody tell me more (which kind of project, can it be an MFC, etc....)

    Reply
  • I enjoyed the article

    Posted by Legacy on 09/26/2003 12:00am

    Originally posted by: Nick

    There might be dozens of other articles like this, but I had trouble finding one! Maybe I'm using search engine wrong, but even now that I know this article is here, this is the only thing I could find:
    
    

    <i><b>System - Table of Contents</b>
    [ more results like this ]
    Find the lowest price for a variety of products: Featured Categories: CodeGuru Sites Interact Of Interest Article Sections Other Section C++ COM-based Technologies Controls Data Frameworks Graphics & Multimedia Internet & Networking Miscellaneous Visual Studio Windows Programming Windows & Dialogs internet.commerce

    Relevance: 97%
    URL:http://codeguru.earthweb.com/system/ServiceTemplate.html<;/i>


    That's the search engine's description of this article. Gee, how am I supposed to figure that one out??

    Reply
  • Beginner question, thanks for the good example

    Posted by Legacy on 08/15/2003 12:00am

    Originally posted by: TimC

    The code in this article works well in it's own MS Visual C++ 6 (new .NET version in the mail) but, when I paste the exact same code into my much bigger project (none of my code getting involved) the call to StartServiceCtrlDispatcher() never results in ServiceMain() getting called. I've fixed this kind of problem in the past by trashing my project and starting fresh in a new one, but what a pain. Any ideas?

    As it turns out, I've experimented with a rather large number of sample Windows service programs (trying to see why I have the above problem.) This one is easily one of the best: simple yet the most complete I've found. I could use it as an example of the right way to write sample programs in general. With luck we'll see more like this one.

    Reply
  • Obvoius

    Posted by Legacy on 08/11/2003 12:00am

    Originally posted by: dakkk

    Hy CodeGuru! You are becoming the laughing stock of everyone that had something to do with CodeGuru not by publishing such an article but rather by allowing some "Neanderthals" to post improper comments.

    No offense but there are a lot of GREEN programmers that might have read the article and found it useful. For all the others just one thing: Did someone put a gun to your head and MADE you read it?? Don't think so ... So it's simple: If you don't find it interesting then don't read it.

    From experience I can say that I would rather look at the way someone implemented a known concept than look in MSDN. Sometimes you may even find some new simple ideas that would help, even if it's a ****o world app...

    It is here that I first found topics about flicker free drawing (things I would never find in MSDN :) for that matter) and they were stated in a HW app.

    So if anyone at CodeGuru has any dignity left then it should "moderate" this pathetic excuse for a "discussion list"

    Reply
  • Codeguru: Please *MODERATE" this list!

    Posted by Legacy on 08/09/2003 12:00am

    Originally posted by: Rodrigo Madera

    This isn't right for a coding page. Administrators *must* edit this nonsense comments.

    It hurts Codeguru's image to let un-supervised comments like these.

    Hire someone to do the job. (How about Brian?)

    Reply
  • Good Attempt

    Posted by Legacy on 08/08/2003 12:00am

    Originally posted by: Bill Gates+++

    I am surprized at the negative comments for this article. Guys if you dont like the article, why to read it all. Read something that you think is new. Ignore known articles on the known subject.

    Reply
  • Last visit

    Posted by Legacy on 08/07/2003 12:00am

    Originally posted by: Mark

    This just about does it.
    At one time this was the prime-programming site and I came every day to read the articles. Yes, some were a little dull or simplistic but the fact is that people have gone to the time and trouble to produce them. No one is forcing anyone else to read the articles or appraise the submissions.
    However, what I do object to is comments that are rude and profane for no other reason than that they can be. And I don't even blame the childish morons who are submitting these comments. I blame the web master for not taking responsibility to ensure that what goes up is, at the very least, sensible and polite criticism. It can still be harsh and pointed but the use of bad language and personal criticism is uncalled for and shows that the submitter has a) poor command of the language and b) cannot control their childish tantrums.
    I'm off to Code Project where all the grown-ups live.
    Bye.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • This paper introduces IBM Java on the IBM PowerLinux 7R2 server and describes IBM's implementation of the Java platform, which includes IBM's Java Virtual Machine and development toolkit.

  • A modern mobile IT strategy is no longer an option, it is an absolute business necessity. Today's most productive employees are not tied to a desk, an office, or a location. They are mobile. And your company's IT strategy has to be ready to support them with easy, reliable, 24/7 access to the business information they need, from anywhere in the world, across a broad range of communication devices. Here's how some of the nation's most progressive corporations are meeting the many needs of their mobile workers …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds