Click here to Skip to main content
13,557,707 members
Click here to Skip to main content
Add your own
alternative version


114 bookmarked
Posted 1 Aug 2002

How to Create a Windows NT/ Windows 2000 Service

, 2 Aug 2002
Rate this:
Please Sign up or sign in to vote.
How to create a Windows NT/ Windows 2000 Service using VC++.


A Windows service is an EXE specially designed to communicate with the SCM (Service Control Manager) of Windows NT/2000. The Service Control Manager (SCM) maintains a database of installed services and driver services, and provides a unified and secure means of controlling them. SCM is started at system boot and it is a remote procedure call (RPC) server. As a developer to try a simple service, we can divide the program into four parts.

  1. Main program of Win32 / Console Application.
  2. A so called ServiceMain(), main program of Service. Entry point of a service.
  3. A Service Control Handler, a function to communicate with SCM.
  4. A Service Installer/ Uninstaller, to register an EXE as a Service.

Firstly, let us take a look at the Main program of the Console application (it can also be a WinMain()).

#include "Winsvc.h" //Header file for Services.
  SERVICE_TABLE_ENTRY Table[]={{"Service1",ServiceMain},{NULL,NULL}};

The only thing done by the main() is to fill a SERVICE_TABLE_ENTRY array. The position [0][0] contains the name of the Service (any string you like). Position [0][1] contains the name of the Service Main function, I specified in the list earlier. It actually is a function pointer to the Service main function. The name can be any thing. Now we start the first step to a service by calling StartServiceCtrlDispatcher() with the SERVICE_TABLE_ENTRY array. Note that the function signature should be of the form. The [1][0] and [1][1] positions are NULL, just to say the end of the array (not a must). We can add more entries to the list if we have more than one service running from the same EXE.

The declaration of a typical ServiceMain():

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)

Now, let us analyze our ServiceMain function.

The main steps of this function are:

  1. Fill the SERVICE_STATUS structure with appropriate values to communicate with the SCM.
  2. Register the Service Control Handler function said earlier in the list.
  3. Call the actual processing functions.

For proceeding, we need two global variables here:

  • SERVICE_STATUS m_ServiceStatus;
  • SERVICE_STATUS_HANDLE m_ServiceStatusHandle;

The ServiceMain() can accept command line arguments just as any C++ main() function. The first parameter contains the number of arguments being passed to the service. There will always be at least one argument. The second parameter is a pointer to an array of string pointers. The first item in the array always points to the service name. The SERVICE_STATUS data structure is used to fill the current state of the Service and notify it to the SCM. We use an API function SetServiceStatus() for the purpose. The data members of SERVICE_STATUS to look for are:

dwServiceType = SERVICE_WIN32; 
dwCurrentState = SERVICE_START_PENDING; //Means Trying To Start(Initially)

dwControlsAccepted = SERVICE_ACCEPT_STOP; accepts Stop/Start only in Service control program, usually in the Control Panel (NT) / Administrative tools (2000). We can also set our service to accept PAUSE and CONTINUE functionality.

In the beginning of the ServiceMain(), we should set the dwCurrentState of SERVICE_STATUS to SERVICE_START_PENDING. This signals the SCM that the service is starting. If any error occurs in the way, we should notify the SCM by passing SERVICE_STOPPED. By default, the SCM will look for an activity from the service and if it fails to show any progress within 2 minutes, SCM kills that service.

The API function RegisterServiceCtrlHandler() is used to set the Service Control Handler Function of the Service with the SCM. The function takes two parameters as earlier, one service name (string) and the pointer to the Service Control Handler Function. That function should be with the signature.

Once we get till here, we now set dwCurrentState as SERVICE_RUNNING to notify that the service has started to function. The next step is to call the actual processing steps.

Now, let us analyze our Service Control Handler function:

The Service Control Handler function is used by the SCM to communicate to the Service program about a user action on the service, like a start, stop, pause or continue. It basically contains a switch statement to deal with each case. Here, we will call appropriate steps to clean up and terminate the process. This function receives an opcode which can have values like SERVICE_CONTROL_PAUSE, SERVICE_CONTROL_CONTINUE, SERVICE_CONTROL_STOP, SERVICE_CONTROL_INTERROGATE etc. We have to write appropriate steps on each.

Now Service Installer/ Uninstaller

For installing a service, we need to make some entries in the system registry. Windows has some APIs to do these steps, instead of using the registry functions. They are CreateService() and DeleteService(). For both these functions, we need to open the SCM database with appropriate rights. I prefer SC_MANAGER_ALL_ACCESS. For installing a service, first open the SCM by OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS). Then invoke the CreateService() with appropriate binary file path of our service. Here also, we have to give the name of our service. We need this name if we want to delete a particular service. In deleting a service, we need to open the specific service first by its name and then invoke the DeleteService() on it. That’s all what we need. Take a look at the code given with it for more details.

Thank You

Anish C.V.

The Code Goes Here:

#include "stdafx.h"
#include "Windows.h"
#include "Winsvc.h"
#include "time.h"

SERVICE_STATUS m_ServiceStatus;
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
BOOL bRunning=true;
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
void WINAPI ServiceCtrlHandler(DWORD Opcode);
BOOL InstallService();
BOOL DeleteService();
int main(int argc, char* argv[])
        printf("\n\nService Installed Sucessfully\n");
        printf("\n\nError Installing Service\n");
        printf("\n\nService UnInstalled Sucessfully\n");
        printf("\n\nError UnInstalling Service\n");
      printf("\n\nUnknown Switch Usage\n\nFor Install 
           use Srv1 -i\n\nFor UnInstall use Srv1 -d\n");
    SERVICE_TABLE_ENTRY DispatchTable[]=
  return 0;

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
  DWORD status;
  DWORD specificError;
  m_ServiceStatus.dwServiceType = SERVICE_WIN32;
  m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  m_ServiceStatus.dwWin32ExitCode = 0;
  m_ServiceStatus.dwServiceSpecificExitCode = 0;
  m_ServiceStatus.dwCheckPoint = 0;
  m_ServiceStatus.dwWaitHint = 0;

  m_ServiceStatusHandle = RegisterServiceCtrlHandler("Service1", 
  if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
  m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  m_ServiceStatus.dwCheckPoint = 0;
  m_ServiceStatus.dwWaitHint = 0;
  if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))

    //Place Your Code for processing here....

void WINAPI ServiceCtrlHandler(DWORD Opcode)
      m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
      m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
      m_ServiceStatus.dwWin32ExitCode = 0;
      m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
      m_ServiceStatus.dwCheckPoint = 0;
      m_ServiceStatus.dwWaitHint = 0;

      SetServiceStatus (m_ServiceStatusHandle,&m_ServiceStatus);

BOOL InstallService()
  char strDir[1024];
  HANDLE schSCManager,schService;

  if (schSCManager == NULL) 
    return false;
  LPCTSTR lpszBinaryPathName=strDir;

  schService = CreateService(schSCManager,"Service1", 
        "The Display Name Needed", // service name to display
     SERVICE_ALL_ACCESS, // desired access 
     SERVICE_WIN32_OWN_PROCESS, // service type 
     SERVICE_DEMAND_START, // start type 
     SERVICE_ERROR_NORMAL, // error control type 
     lpszBinaryPathName, // service's binary 
     NULL, // no load ordering group 
     NULL, // no tag identifier 
     NULL, // no dependencies
     NULL, // LocalSystem account
     NULL); // no password

  if (schService == NULL)
    return false; 

  return true;

BOOL DeleteService()
  HANDLE schSCManager;
  SC_HANDLE hService;

  if (schSCManager == NULL)
    return false;
  if (hService == NULL)
    return false;
    return false;
    return false;

return true;


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

C.V Anish
Web Developer
United States United States
A Developer from India. Concentrating on the Microsoft Technologies. VC++ and VB.

You may also be interested in...


Comments and Discussions

Questionerror lnk2019 external symbol InstallService Pin
antonioFP10-Oct-14 14:01
memberantonioFP10-Oct-14 14:01 
GeneralSuperbly working Pin
Habeeballah Hasnoddin16-Jun-11 1:45
memberHabeeballah Hasnoddin16-Jun-11 1:45 
Generaleasy and good Pin
khosob27-Dec-10 23:24
memberkhosob27-Dec-10 23:24 
GeneralError 1053: The service did not respond to the start or control request in a timely fashion Pin
marina15092-Jun-10 9:25
membermarina15092-Jun-10 9:25 
QuestionCalling an another executable in the same project thru services??? Pin
jain_MS23-Nov-09 3:21
memberjain_MS23-Nov-09 3:21 
Questionhow can i run the service? Pin
raaf2721-Oct-09 0:33
memberraaf2721-Oct-09 0:33 
QuestionHow to make the service access desktop application. Pin
gtag7-Oct-09 18:04
membergtag7-Oct-09 18:04 
AnswerRe: How to make the service access desktop application. Pin
Anish C.V9-Oct-09 0:47
memberAnish C.V9-Oct-09 0:47 
GeneralThe article is very nice and easy Pin
devesh.tyagi26-Feb-09 0:59
memberdevesh.tyagi26-Feb-09 0:59 
GeneralRe: The article is very nice and easy Pin
Anish C.V9-Oct-09 0:50
memberAnish C.V9-Oct-09 0:50 
GeneralRe: The article is very nice and easy Pin
julien.bourgoin24-Jun-11 3:48
memberjulien.bourgoin24-Jun-11 3:48 
QuestionHow to make a com executable server as a windows service? Pin
edwinwu30-Oct-07 8:45
memberedwinwu30-Oct-07 8:45 
AnswerRe: How to make a com executable server as a windows service? Pin
HQH5-Nov-07 16:03
memberHQH5-Nov-07 16:03 
QuestionI can't stop Service Pin
Dang Le Quang30-Sep-07 16:05
memberDang Le Quang30-Sep-07 16:05 
QuestionWhy does service doesn't install Pin
bazmikhan200010-Jul-07 4:52
memberbazmikhan200010-Jul-07 4:52 
Generalwhere the new service will be added after running code Pin
Vinamrata9-Jul-07 0:54
memberVinamrata9-Jul-07 0:54 
Questionwhy doesn't sample code compile? Pin
gongchengshi31-May-07 7:49
membergongchengshi31-May-07 7:49 
AnswerRe: why doesn't sample code compile? Pin
julien.bourgoin24-Jun-11 3:45
memberjulien.bourgoin24-Jun-11 3:45 
GeneralVisual C++ 6.0. Pin
Plennguyen9-May-07 18:19
memberPlennguyen9-May-07 18:19 
AnswerRe: Visual C++ 6.0. Pin
seneralex11-May-07 1:47
memberseneralex11-May-07 1:47 
GeneralService Questions Pin
AYcoder14-Aug-06 1:37
memberAYcoder14-Aug-06 1:37 
QuestionInvoking Windows services Pin
Mohan Bisht4-Jul-06 21:52
memberMohan Bisht4-Jul-06 21:52 
AnswerRe: Invoking Windows services Pin
HQH5-Nov-07 16:05
memberHQH5-Nov-07 16:05 
GeneralIt is very good, easily understood very much Pin
ssssss2419-Sep-05 22:06
memberssssss2419-Sep-05 22:06 
GeneralInitialisation failure Pin
jan lucas29-Jun-05 1:50
memberjan lucas29-Jun-05 1:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01-2016 | 2.8.180515.1 | Last Updated 3 Aug 2002
Article Copyright 2002 by C.V Anish
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid