Re: Windows service Vs Console app performance

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Ollie Leahy (oliver.leahy_at_gmail.com)
Date: 06/24/04


Date: Thu, 24 Jun 2004 04:36:23 -0700


Thanks I'll look into the priorities of the processes

Unfortunately the code is fairly long, since it has
to set up the service and all, but, here goes,
sample -d runs as a console app,
and the familiar sample -install and then
sample -start will run it as a service ...

here goes ....

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

SERVICE_STATUS status;
SERVICE_STATUS_HANDLE statusHandle;
DWORD err = 0;
TCHAR errstr[256];
BOOL dbg = FALSE;

VOID WINAPI serviceCtrl(DWORD dwCtrlCode);
VOID WINAPI serviceMain(DWORD dwArgc, LPTSTR *lpszArgv);
VOID CmdInstallService();
VOID CmdRemoveService();
VOID CmdStartService(int argc, char **argv);
VOID CmdStopService(int argc, char **argv);
void CmdDebugService(int argc, char ** argv);
BOOL WINAPI ControlHandler ( DWORD ctrl );
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );

char reader_buf[1024];
char * SZSERVICENAME = "A Sample Service";
char * SZAPPNAME = "tst";
char * SZSERVICEDISPLAYNAME = "A Sample Service";
char * SZDEPENDENCIES = "";

/*
 *
 */
int
appMain(int ac, char * av[])
{
    time_t now = 0;
    int n = 0, m = 0, j = 0;
    FILE * fp = NULL;
    HANDLE ph;
    DWORD cl;

    ph = GetCurrentProcess();
    cl = GetPriorityClass(ph);

    now = time(NULL);
    for (n = 0; n < 100000; n++ ) {
        for (m = 0; m < 10000; m++) {
            j = m * n;
        }
    }
    fp = fopen("c:/sample.log", "a+");
    if (fp != NULL) {
        fprintf(fp, "(%d) Run time : %d\n", cl, time(NULL) - now);
    } else {
        printf("(%d) Run time : %d\n", cl, time(NULL) - now);
    }
    return EXIT_SUCCESS;
}

/*
 *
 */
int
appStop(void)
{
    return 0;
}

/*
 * Only auto start on a non-debug build, so that during
development
 * a reboot will always stop a rogue service
 */
#if defined (DEBUG)
#define SERVICE_START_OPTION SERVICE_DEMAND_START
#else
#define SERVICE_START_OPTION SERVICE_AUTO_START
#endif

/*
 * One argument
 * -install registers the service with the
 * Service Control Manager.
 * -remove Removes the service from the
 * Service Control Manager.
 * -start Starts the service.
 * -stop Stops the service.
 */
int
main(int argc, char **argv)
{
        SERVICE_TABLE_ENTRY dispatchTable[] = {
                {TEXT(SZSERVICENAME),
(LPSERVICE_MAIN_FUNCTION)serviceMain},
                {NULL, NULL}
        };

        if ((argc > 1) && ((*argv[1] == '-'))) {
                if (_stricmp("-install", argv[1]) == 0) {
                        CmdInstallService();
                } else if (_stricmp( "-remove", argv[1]) == 0) {
                        CmdRemoveService();
                } else if (_stricmp("-start", argv[1]) == 0) {
                        CmdStartService(argc, argv);
                } else if (_stricmp("-stop", argv[1]) == 0) {
                        CmdStopService(argc, argv);
                } else if (_stricmp("-d", argv[1]) == 0) {
                        dbg = TRUE;
                        CmdDebugService(argc, argv);
                } else {
                        goto dispatch;
                }
                return 0;
        }
dispatch:
        /*
         * Help message when the command is run from the console.
         */
        printf( "%s -install to install the service\n",
SZAPPNAME );
        printf( "%s -remove to remove the service\n",
SZAPPNAME );
        printf( "%s -start to start the service\n", SZAPPNAME
);
        printf( "%s -stop to stop the service\n", SZAPPNAME
);
        printf( "\nStartServiceCtrlDispatcher being called.\n" );
        printf( "This may take several seconds. Please wait.\n" );

        StartServiceCtrlDispatcher(dispatchTable);

        return 0;
}

/*
 *
 */
void WINAPI
serviceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
        /*
         * Register service control handler
         */
        statusHandle = RegisterServiceCtrlHandler(TEXT(SZSERVICENAME),
                                                     serviceCtrl);
        if (!statusHandle)
                goto finished;

        /*
         * Initialise SERVICE_STATUS
         */
        status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
        status.dwServiceSpecificExitCode = 0;
        /*
         * Status has to be reported to the SCM, since there is nothing
         * else to do we go straight from pending to running
         */
        if (!ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000))
                goto finished;

        if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
                goto finished;

        appMain(dwArgc, lpszArgv);

finished:
        /*
         * Tell SCM service is stopping
         */
        if (statusHandle)
                (VOID)ReportStatusToSCMgr(SERVICE_STOPPED, err, 0);
}

/*
 * This function is called by the SCM whenever
 * ControlService() is called on this service.
 */
VOID WINAPI
serviceCtrl(DWORD dwCtrlCode)
{
        switch(dwCtrlCode){
        /*
         * Stop the service.
         */
        case SERVICE_CONTROL_STOP:
                status.dwCurrentState = SERVICE_STOP_PENDING;
                appStop();
                break;
        /*
         * Update the service status.
         */
        case SERVICE_CONTROL_INTERROGATE:
                break;
        }
        ReportStatusToSCMgr(status.dwCurrentState, NO_ERROR, 0);
}

/*
 * Sets the current status of the service and
 * reports it to the Service Control Manager
 *
 * dwCurrentState - the state of the service
 * dwWin32ExitCode - error code to report
 * dwWaitHint - worst case estimate to next checkpoint
 */
BOOL
ReportStatusToSCMgr(DWORD dwCurrentState,
                         DWORD dwWin32ExitCode,
                         DWORD dwWaitHint)
{
        static DWORD checkpoint = 1;
        BOOL rc = TRUE;

        if (dwCurrentState == SERVICE_START_PENDING)
                status.dwControlsAccepted = 0;
        else
                status.dwControlsAccepted = SERVICE_ACCEPT_STOP;

        status.dwCurrentState = dwCurrentState;
        status.dwWin32ExitCode = dwWin32ExitCode;
        status.dwWaitHint = dwWaitHint;

        if ((dwCurrentState == SERVICE_RUNNING) ||
                                (dwCurrentState == SERVICE_STOPPED))
                status.dwCheckPoint = 0;
        else
                status.dwCheckPoint = checkpoint++;
        /*
         * Report the status of the service to the service
         * control manager.
         */
        rc = SetServiceStatus( statusHandle, &status);
        return rc;
}

/*
 *
 */
void
CmdInstallService()
{
    SC_HANDLE srv;
    SC_HANDLE svrmgr;

    TCHAR path[512];

    if ( GetModuleFileName( NULL, path, 512 ) == 0 ) {
        printf(TEXT("Unable to install %s - %s\n"),
                        TEXT(SZSERVICEDISPLAYNAME),
                        GetLastErrorText(errstr, 256));
        return;
    }
    printf("Install path is <%s>\n", path);
    svrmgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (svrmgr) {
        srv = CreateService(
                        svrmgr, // SCManager
database
                        TEXT(SZSERVICENAME), // name of service
                        TEXT(SZSERVICEDISPLAYNAME), // name to display
                        SERVICE_ALL_ACCESS, // desired access
                        SERVICE_WIN32_OWN_PROCESS, // service type
                        SERVICE_START_OPTION, // start type
                        SERVICE_ERROR_NORMAL, // error control
type
                        path, // service's binary
                        NULL, // no load ordering
group
                        NULL, // no tag identifier
                        TEXT(SZDEPENDENCIES), // dependencies
                        NULL, // LocalSystem
account
                        NULL); // no password

        if ( srv ) {
            printf(TEXT("%s installed.\n"),
                                        TEXT(SZSERVICEDISPLAYNAME) );
            CloseServiceHandle(srv);
        } else {
            printf(TEXT("CreateService fail - %s\n"),
                                        GetLastErrorText(errstr, 256));
        }
        CloseServiceHandle(svrmgr);
    } else
        printf(TEXT("OpenSCManager fail - %s\n"),

GetLastErrorText(errstr,256));
}

/*
 * Stops and removes the service
 */
void
CmdRemoveService()
{
    SC_HANDLE srv;
    SC_HANDLE svrmgr;

    svrmgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    
    if (svrmgr) {
        srv = OpenService(svrmgr, TEXT(SZSERVICENAME),
SERVICE_ALL_ACCESS);

        if (srv) {
            /*
             * First make sure that the service is stopped.
             */
            if (ControlService(srv, SERVICE_CONTROL_STOP, &status)) {
                printf(TEXT("Stopping %s."),
TEXT(SZSERVICEDISPLAYNAME));
                Sleep( 1000 );

                while(QueryServiceStatus(srv, &status)) {
                    if (status.dwCurrentState == SERVICE_STOP_PENDING) {
                        printf(TEXT("."));
                        Sleep( 1000 );
                        } else {
                            break;
                        }
                }

                if (status.dwCurrentState == SERVICE_STOPPED)
                    printf(TEXT("\n%s stopped.\n"),
                                            TEXT(SZSERVICEDISPLAYNAME));
                else
                    printf(TEXT("\n%s failed to stop.\n"),

TEXT(SZSERVICEDISPLAYNAME));

            }

            /*
             * Now remove the service
             */
            if( DeleteService(srv) )
                printf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME)
);
            else
                printf(TEXT("DeleteService fail - %s\n"),

GetLastErrorText(errstr,256));

            CloseServiceHandle(srv);
        } else {
            printf(TEXT("OpenService fail - %s\n"),
                                        GetLastErrorText(errstr,256));
        }

        CloseServiceHandle(svrmgr);
    } else
    printf(TEXT("OpenSCManager fail - %s\n"),
GetLastErrorText(errstr,256));
}

/*
 * Starts the service.
 */
void
CmdStartService(int argc, char ** argv)
{
        SC_HANDLE srv;
        SC_HANDLE svrmgr;

        svrmgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    
        if (svrmgr) {
            srv = OpenService(svrmgr,
                                    TEXT(SZSERVICENAME),
                                    SERVICE_ALL_ACCESS);
            if (srv) {
                if(StartService(srv, 0, NULL)) {
                    printf(TEXT("Starting %s."),
TEXT(SZSERVICEDISPLAYNAME));
                    Sleep(1000);

                    while(QueryServiceStatus(srv, &status)) {
                        if (status.dwCurrentState ==
SERVICE_START_PENDING) {
                            printf(TEXT("."));
                            Sleep( 1000 );
                        } else {
                            break;
                        }
                    }
                    if (status.dwCurrentState == SERVICE_RUNNING)
                        printf(TEXT("\n%s started.\n"),
                                            TEXT(SZSERVICEDISPLAYNAME));
                    else
                        printf(TEXT("\n%s failed to start.\n"),
                                            TEXT(SZSERVICEDISPLAYNAME));
                }
                CloseServiceHandle(srv);
            }else
                printf(TEXT("OpenService fail - %s\n"),
                                    GetLastErrorText(errstr,256));
            CloseServiceHandle(svrmgr);
        } else
            printf(TEXT("OpenSCManager fail - %s\n"),
                                     GetLastErrorText(errstr,256));
}

/*
 * Stops the service.
 */
void
CmdStopService(int argc, char ** argv)
{
    SC_HANDLE srv;
    SC_HANDLE svrmgr;

    svrmgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

    if (svrmgr) {
        srv = OpenService(svrmgr, TEXT(SZSERVICENAME),
SERVICE_ALL_ACCESS);
        if (srv) {
            /*
             * First make sure that the service is stopped.
             */
            if (ControlService(srv, SERVICE_CONTROL_STOP, &status)) {
                printf(TEXT("Stopping %s."),
TEXT(SZSERVICEDISPLAYNAME));
                Sleep( 1000 );
                while(QueryServiceStatus(srv, &status)) {
                    if (status.dwCurrentState == SERVICE_STOP_PENDING) {
                        printf(TEXT("."));
                        Sleep( 1000 );
                    } else {
                        break;
                    }
                }
                if (status.dwCurrentState == SERVICE_STOPPED)
                    printf(TEXT("\n%s stopped.\n"),

TEXT(SZSERVICEDISPLAYNAME));
                else
                    printf(TEXT("\n%s failed to stop.\n"),

TEXT(SZSERVICEDISPLAYNAME));
            }
            CloseServiceHandle(srv);
        } else
        printf(TEXT("OpenService fail - %s\n"),
GetLastErrorText(errstr,256));
        CloseServiceHandle(svrmgr);
    } else
        printf(TEXT("OpenSCManager fail - %s\n"),
                                GetLastErrorText(errstr,256));
}

/*
 * Debugging support function,
 *
 * Control C or control break will stop the
 * service in debug mode.
 */
BOOL WINAPI
ControlHandler ( DWORD ctrl )
{
        switch( ctrl ) {
        case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
        case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
                printf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
                appStop();
                return TRUE;
        }
        return FALSE;
}

/*
 * Debug support function, run the service as
 * a consol mode application.
 *
 * argc - number of command line arguments
 * argv - array of command line arguments
 */
void
CmdDebugService(int argc, char ** argv)
{
        DWORD dwArgc;
        LPTSTR *lpszArgv;

#ifdef UNICODE
        lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
#else
        dwArgc = (DWORD) argc;
        lpszArgv = argv;
#endif

        printf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));

        SetConsoleCtrlHandler( ControlHandler, TRUE );

        appMain( dwArgc, lpszArgv );
}
/*
 * Copy text for error code into a string.
 */
LPTSTR
GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
{
    DWORD rc;
    LPTSTR tmp = NULL;

    rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                       FORMAT_MESSAGE_FROM_SYSTEM |
                       FORMAT_MESSAGE_ARGUMENT_ARRAY,
                              NULL,
                              GetLastError(),
                              LANG_NEUTRAL,
                              (LPTSTR)&tmp,
                              0,
                              NULL);

    /*
     * A truncated message is worse than none at all, so return nothing
     * if the whole message does not fit.
     */
    if ( !rc || ( (long)dwSize < (long)rc+14 ) ) {
        lpszBuf[0] = TEXT('\0');
    } else {
        int n = GetLastError();
        /*
         * Strip cr/lf
         */
        tmp[lstrlen(tmp)-2] = TEXT('\0');
        printf(lpszBuf, TEXT("%s (0x%x)"), tmp, n);
    }

    if ( tmp )
        LocalFree((HLOCAL) tmp );

    return lpszBuf;
}

*** Sent via Devdex http://www.devdex.com ***
Don't just participate in USENET...get rewarded for it!



Relevant Pages