Click here to Skip to main content
15,883,883 members
Articles / Programming Languages / C++
Article

Become a service

Rate me:
Please Sign up or sign in to vote.
3.16/5 (19 votes)
15 May 20034 min read 95.9K   2.4K   47   19
This article introduces a set of C functions you can use in you projects to write windows services in few lines of code

Introduction

Write a service isn't allways easy, specialy when you have a lot of existing code to deal with. The OSR_Service toolkit is a set of C files you can include into your C/C++ projects to write window services functionalities in few lines.

The ServiceStart function

The ServiceStart function start the service. It may be called at the begin of the application.
OSR_ERROR OSR_CALL ServiceStart(OSR_SERVICE_PARAMS * Params)

Parameters

Params

Pointer to the OSR_SEVICE_PARAMS structure the contains the servis start parameters and preferences.

Return Values

If the function succeeds, the return value is OSR_SUCCESS.

Remarks

Ideally, this function must be called in the main function (WinMain) before the the code the application may execute when the service is running.

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine,int nCmdShow)
{
     OSR_SERVICE_PARAMS params;
    params.ServiceDependencies[0] = 0;
    params.ServiceDependencies[1] = 0;
    
    strcpy((char *)params.ServiceLogin,".\\Administrateur");
    strcpy((char *)params.ServicePassword,"AdminPassword");
    strcpy((char *)params.ServiceName,"OSR_SAPMPLE_SERVICE");
    strcpy((char *)params.ServiceNameDisplay,"OSR sample service");
    
    params.ServiceAcceptedCommands = SERVICE_ACCEPT_STOP|
                        SERVICE_ACCEPT_PAUSE_CONTINUE|SERVICE_ACCEPT_SHUTDOWN;
    params.ServiceStartType = SERVICE_DEMAND_START;

        
    if(strcmp(lpCmdLine,"install") == 0)
    {
        // Install the service
        //**********************
        ServiceInstall(&params);
    }
    else
    {    
        if(strcmp(lpCmdLine,"uninstall") == 0)
        {
            
            // Uninstall the service
            //**********************
            ServiceUninstall(&params);
        }
        else
        {
        
            // Start the service
            //**********************
            ServiceStart(&params);

            // The service is now running
            //***************************
            while(!stop_request)
            {
                // Do something
                //*******************
                printf("I'm a running service\n");
                Sleep(1000);
            }
        }
    }
        
    return 0;
}

The OSR_APP_XXX Functions

Four callback functions must be wrote by the user to handle the service messages. This functions are :
int OSR_CALL OSR_APP_START(int step);
int OSR_CALL OSR_APP_STOP(int step);
int OSR_CALL OSR_APP_PAUSE(int step);
int OSR_CALL OSR_APP_CONTINUE(int step);
int OSR_CALL OSR_APP_SHUTDOWN(int step);

When the service receives a message form the service manager, requisting for a new status (eg. the service is running, and we want to stop it), the OSR_APP_STOP is called one time. According to the returned value by this function, the function will be called as long as is necesary to complete the stop process.

Explanation

As decribed in the fig 1., a service has 3 major states (STOPED,RUNNING,PAUSED) and 4 pending states (START PENDING,PAUSE PENDING,CONTINUE PENDING,STOP PENDING) .


Service states
fig1. service states


The major states are states requested by a service manager (eg. stop the service), and the pending states are transitory states between 2 major states. A way to the application to say to the service manager "Ok! I'm doing the required things to stop the application, please wait".

Parameters

step

The step is an incremential value sent to the function every time the function is called under the same status change.

Return Values

The function can return 3 values
ValueMeaning
OSR_SERVICE_WAIT
The init process is not completed, the service stay in a pending state, and this function will be called again and the step value increased.
OSR_SERVICE_DONE
The init process is completed. The service can be in the requested state.
OSR_SERVICE_ABORT
The init process can't be done, or fail. The status can't be changed.

Remarks

All these functions must be return a result to allow the status update.
For the OSR_APP_START function, you may launch a new thread to run something after the start initialization.
Here a simple start process in 3 steps.
int OSR_CALL OSR_APP_START(int step)
{
    switch(step)
    {
    case 0:
        OpenLogFile();
        return OSR_SERVICE_WAIT
    break;

    case 1:
        InitSocket();
        return OSR_SERVICE_WAIT;
    break;

    case 2:
        return OSR_SERVICE_DONE;
    break;
}

The OSR_SERVICE_PARAMS structure

typedef struct _OSR_SERVICE_PARAMS
{
// Name of the service
UCHAR ServiceName[STR_CHAR32];     
// Service name displayed in the service manager
UCHAR ServiceNameDisplay[STR_CHAR32]; 
// Dependencies name array
UCHAR ServiceDependencies[STR_CHAR64];    
// Service start mode    
U32BIT ServiceStartType;
// Login used by the service                
UCHAR ServiceLogin[STR_CHAR32];            
// Password used by the service
UCHAR ServicePassword[STR_CHAR32];
// Commands you can use with this service            
U32BIT ServiceAcceptedCommands;            
}OSR_SERVICE_PARAMS;

Members

ServiceName

Null-terminated string that names the service. "\" and "/" characters are invalid in the service name.

ServiceNameDisplay

Null-terminated string that is to be used by user interface programs to identify the service.

ServiceDependencies

Double null-terminated array of null-separated names of services or load ordering groups that the system must start before this service. Specify NULL if no dependencies are required.

- "NetworkService\0LogService\0\0" means NetworkService and LogService may be started before allow your service to start.
- "\0\0" means no dependencied are defined.

ServiceStartType

Specifies when to start the service. You must specify one of the following start types
ValueMeaning
SERVICE_AUTO_START
Specifies a service to be started automatically by the service control manager during system startup.
SERVICE_DEMAND_START
Specifies a service to be started by the service control manager when a process calls the StartService function.
SERVICE_DISABLEDSpecifies a service that can no longer be started.

ServiceLogin

Null-terminated string that names the service. You must use an account name in the form DomainName\UserName. Because the account belongs to the built-in domain, you can specify .\UserName. You also must specify the LocalSystem account. If you specify an empty string ("\0") LocalSystem account is used.

ServicePassword

Null-terminated string that contains the password to the account name specified by the ServiceLogin parameter. If the string is empty, the service has no password.

Using the sample

This project is provided with a sample project who demostrate how to integrate the osr_service code in "real" code. The sample code include a precompiled binary - for X86 win32 platforms - who run in this way.

sample_service [install|uninstall] to install or remove the service from the service manager. For your convenience I build it with the system account, ie. no change is require for a first try.

The sample, and basicaly all the osr_service functions run in a debug mode, who log all the errors using the OutputDebugString log method. To display the logs you must use a tool like DebugView from the SysInternals guys (www.sysinternals.com). This tool is free.

License

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


Written By
Web Developer
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralImportant bugfix Pin
fatorange10-May-04 12:00
fatorange10-May-04 12:00 
GeneralCan't compile with VC7.0 Pin
rromerot6-Apr-04 7:40
rromerot6-Apr-04 7:40 
GeneralRELEASE version does not work .. Pin
Member 17904013-Oct-03 4:04
Member 17904013-Oct-03 4:04 
GeneralRe: RELEASE version does not work .. Pin
fato5-Nov-03 4:22
fato5-Nov-03 4:22 
QuestionError code: ERROR_SXS_ASSEMBLYNOTFOUND what is this? Pin
girishnadig18-Sep-03 6:54
girishnadig18-Sep-03 6:54 
General1000th version of "Hello World" Pin
Anonymous16-May-03 14:36
Anonymous16-May-03 14:36 
just see yr strcpy instead of the lstrcpy in the code snippet. I have known it is another stupid article in codeproject againSleepy | :zzz:
Generaladvantage of lstrcpy over strcpy? Pin
ncpga21-May-03 6:55
ncpga21-May-03 6:55 
GeneralFile missing Pin
Fgadaut6-May-03 22:24
Fgadaut6-May-03 22:24 
GeneralRe: File missing Pin
mbenella9-May-03 1:54
mbenella9-May-03 1:54 
GeneralRe: File missing Pin
fato9-May-03 4:19
fato9-May-03 4:19 
Generalnew release Pin
fato9-Apr-03 12:30
fato9-Apr-03 12:30 
GeneralYour licence makes it useless Pin
Andreas Saurwein7-Apr-03 5:06
Andreas Saurwein7-Apr-03 5:06 
GeneralRe: Your licence makes it useless Pin
Chris Losinger7-Apr-03 5:21
professionalChris Losinger7-Apr-03 5:21 
GeneralRe: Your licence makes it useless Pin
Andreas Saurwein7-Apr-03 5:53
Andreas Saurwein7-Apr-03 5:53 
GeneralRe: Your licence makes it useless Pin
fato7-Apr-03 6:38
fato7-Apr-03 6:38 
GeneralTry my service wizard Pin
Dudi Avramov5-Apr-03 21:43
Dudi Avramov5-Apr-03 21:43 
GeneralRe: Try my service wizard Pin
TW6-Apr-03 4:46
TW6-Apr-03 4:46 
GeneralRe: Try my service wizard Pin
fato6-Apr-03 5:57
fato6-Apr-03 5:57 
GeneralRe: Try my service wizard Pin
TW7-Apr-03 22:09
TW7-Apr-03 22:09 

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.