Recent Post

Categories

Archives

Cow Computing

09 Dec 3

Implementing a Windows Service in C

Days ago, my colleague wanted to have his program written as a window service, and has no clue doing it. I searched online and came across some info, and then compiled the following program.

/*
* Service.c
*
*/

#include <windows.h>
#include <stdio.h>

SERVICE_STATUS          ServiceStatus;
SERVICE_STATUS_HANDLE   hStatus;

int WriteToLog(char* str)
{
    FILE* log;
    log = fopen("C:\\CowService\\log.txt", "a+");
    fprintf(log, "%s\n", str);
    fclose(log);

    return 0;
}

int InitService()
{
    int result;
    result = WriteToLog("Service Started.");
    return(result);
}

// Handler to be registered and called when user interact with the service. (inside the "Windows Service")
void ControlHandler(DWORD request)
{
    switch(request)
    {
        case SERVICE_CONTROL_STOP:
            WriteToLog("Service Closed");
            ServiceStatus.dwWin32ExitCode = 0;
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus (hStatus, &ServiceStatus);
            return;
        case SERVICE_CONTROL_SHUTDOWN:
            WriteToLog("Service Closed");
            ServiceStatus.dwWin32ExitCode = 0;
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            SetServiceStatus (hStatus, &ServiceStatus);
            return;
        default:
            break;
    }
    SetServiceStatus (hStatus, &ServiceStatus);
    return;
}

void ServiceMain(int argc, char** argv)
{
    int error;

    // Initialize and set the state of the service to be "Pending"
    ServiceStatus.dwServiceType = SERVICE_WIN32;
    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted   =  SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwServiceSpecificExitCode = 0;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint = 0;

    hStatus = RegisterServiceCtrlHandler("CowService", (LPHANDLER_FUNCTION)ControlHandler);
    if (hStatus == (SERVICE_STATUS_HANDLE)0)
    {
        return;
    }

    error = InitService();
    if (error)
    {
        // Error, set the service state to "Stopped" and return
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        ServiceStatus.dwWin32ExitCode = -1;
        SetServiceStatus(hStatus, &ServiceStatus);

        return;
    }

    // Set the service state to be "Running"
    ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    SetServiceStatus(hStatus, &ServiceStatus);

    while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
    {
        // while the service is on, do whatever you wish here.
        int result = WriteToLog("Service is Running\n");
        Sleep(2000);
    }

    return;
}

int main()
{
    // Create service table entry to be registered
    SERVICE_TABLE_ENTRY ServiceTable[2];
    ServiceTable[0].lpServiceName = "CowService";
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

    // Setting the entry NULL to indicate it's the end of the service table entry
    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;

    StartServiceCtrlDispatcher(ServiceTable);

    return 0;
}

The code is straightforward, and comments should have spoken for itself.

However, to have the service program working, you have to register it with the “Windows Service” by issuing

// sc create <servcie name> bin_path= <location to the service program>
sc create CowService bin_path= C:\CowService.exe
Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Reddit
  • StumbleUpon
  • Twitter

No Comments »

No comments yet.

Leave a comment