Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Become a service

0.00/5 (No votes)
15 May 2003 1  
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
Value Meaning
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
Value Meaning
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_DISABLED Specifies 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