Windows Services Programming 15

 

 

 

 

 

Starting a Windows Service Example

 

To start a service, a service control program opens a handle to an installed database and then specifies the handle in a call to the StartService() function. After starting the service, the program uses the members of the SERVICE_STATUS_PROCESS structure returned by the QueryServiceStatusEx() function to track the progress of the service. The DoStartSvc() function in the following code fragment example shows how to start a service. The szSvcName variable is a global variable that contains the name of the service to be started.

 

// Purpose: Starts the service if possible

// Parameters: None

// Return value: None

void __stdcall DoStartSvc(void)

{

    SERVICE_STATUS_PROCESS ssStatus;

    DWORD dwOldCheckPoint;

    DWORD dwStartTickCount;

    DWORD dwWaitTime;

    DWORD dwBytesNeeded;

 

    // Get a handle to the SCM database

    schSCManager = OpenSCManager(

        NULL,                    // local computer

        NULL,                    // servicesActive database

        SC_MANAGER_ALL_ACCESS);  // full access rights

 

    if (schSCManager == NULL)

    {

        wprintf(L"OpenSCManager() failed, error %u\n", GetLastError());

        return;

    }

      else

            wprintf(L"OpenSCManager() is OK!\n");

 

    // Get a handle to the service

    schService = OpenService(

        schSCManager,         // SCM database

        szSvcName,            // name of service

        SERVICE_ALL_ACCESS);  // full access

 

    if (schService == NULL)

    {

        wprintf(L"OpenService() failed, error %u\n", GetLastError());

        CloseServiceHandle(schSCManager);

        return;

    }

      else

            wprintf(L"OpenService() is working!\n");

 

    // Check the status in case the service is not stopped

    if (!QueryServiceStatusEx(

            schService,                     // handle to service

            SC_STATUS_PROCESS_INFO,         // information level

            (LPBYTE) &ssStatus,             // address of structure

            sizeof(SERVICE_STATUS_PROCESS), // size of structure

            &dwBytesNeeded))              // size needed if buffer is too small

    {

        wprintf(L"QueryServiceStatusEx() failed, error %u\n", GetLastError());

        CloseServiceHandle(schService);

        CloseServiceHandle(schSCManager);

        return;

    }

      else

            wprintf(L"QueryServiceStatusEx() is fine!\n");

 

    // Check if the service is already running. It would be possible

    // to stop the service here, but for simplicity this example just returns

    if(ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)

    {

        wprintf(L"Cannot start the service because it is already running!\n");

        CloseServiceHandle(schService);

        CloseServiceHandle(schSCManager);

        return;

    }

 

    // Save the tick count and initial checkpoint

    dwStartTickCount = GetTickCount();

    dwOldCheckPoint = ssStatus.dwCheckPoint;

 

    // Wait for the service to stop before attempting to start it

    while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING)

    {

        // Do not wait longer than the wait hint. A good interval is

        // one-tenth of the wait hint but not less than 1 second

        // and not more than 10 seconds

        dwWaitTime = ssStatus.dwWaitHint / 10;

 

        if(dwWaitTime < 1000)

            dwWaitTime = 1000;

        else if (dwWaitTime > 10000)

            dwWaitTime = 10000;

 

        Sleep(dwWaitTime);

 

        // Check the status until the service is no longer stop pending

        if (!QueryServiceStatusEx(

                schService,                     // handle to service

                SC_STATUS_PROCESS_INFO,         // information level

                (LPBYTE) &ssStatus,             // address of structure

                sizeof(SERVICE_STATUS_PROCESS), // size of structure

                &dwBytesNeeded))              // size needed if buffer is too small

        {

            wprintf(L"QueryServiceStatusEx() failed, error %u\n", GetLastError());

            CloseServiceHandle(schService);

            CloseServiceHandle(schSCManager);

            return;

        }

            else

                  wprintf(L"QueryServiceStatusEx() is pretty fine!\n");

 

        if (ssStatus.dwCheckPoint > dwOldCheckPoint)

        {

            // Continue to wait and check

            dwStartTickCount = GetTickCount();

            dwOldCheckPoint = ssStatus.dwCheckPoint;

        }

        else

        {

            if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)

            {

                wprintf(L"Timeout waiting for service to stop\n");

                CloseServiceHandle(schService);

                CloseServiceHandle(schSCManager);

                return;

            }

        }

    }

 

    // Attempt to start the service

    if (!StartService(

            schService,  // handle to service

            0,           // number of arguments

            NULL))       // no arguments

    {

        wprintf(L"StartService() failed, error %u\n", GetLastError());

        CloseServiceHandle(schService);

        CloseServiceHandle(schSCManager);

        return;

    }

    else

            wprintf(L"Service start pending...\n");

 

    // Check the status until the service is no longer start pending.

    if (!QueryServiceStatusEx(

            schService,                     // handle to service

            SC_STATUS_PROCESS_INFO,         // info level

            (LPBYTE) &ssStatus,             // address of structure

            sizeof(SERVICE_STATUS_PROCESS), // size of structure

            &dwBytesNeeded))              // if buffer too small

    {

        wprintf(L"QueryServiceStatusEx() failed, error %u\n", GetLastError());

        CloseServiceHandle(schService);

        CloseServiceHandle(schSCManager);

        return;

    }

      else

            wprintf(L"QueryServiceStatusEx() is working!\n");

 

    // Save the tick count and initial checkpoint.

    dwStartTickCount = GetTickCount();

    dwOldCheckPoint = ssStatus.dwCheckPoint;

 

    while (ssStatus.dwCurrentState == SERVICE_START_PENDING)

    {

        // Do not wait longer than the wait hint. A good interval is

        // one-tenth the wait hint, but no less than 1 second and no

        // more than 10 seconds

        dwWaitTime = ssStatus.dwWaitHint / 10;

 

        if(dwWaitTime < 1000)

            dwWaitTime = 1000;

        else if (dwWaitTime > 10000)

            dwWaitTime = 10000;

 

        Sleep(dwWaitTime);

 

        // Check the status again

        if (!QueryServiceStatusEx(

            schService,             // handle to service

            SC_STATUS_PROCESS_INFO, // info level

            (LPBYTE) &ssStatus,             // address of structure

            sizeof(SERVICE_STATUS_PROCESS), // size of structure

            &dwBytesNeeded))                // if buffer too small

        {

            wprintf(L"QueryServiceStatusEx() failed, error %u\n", GetLastError());

            break;

        }

            else

                  wprintf(L"QueryServiceStatusEx() is pretty damn OK!\n");

 

        if(ssStatus.dwCheckPoint > dwOldCheckPoint)

        {

            // Continue to wait and check.

            dwStartTickCount = GetTickCount();

            dwOldCheckPoint = ssStatus.dwCheckPoint;

        }

        else

        {

            if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)

            {

                // No progress made within the wait hint

                break;

            }

        }

    }

 

    // Determine whether the service is running

    if (ssStatus.dwCurrentState == SERVICE_RUNNING)

    {

        wprintf(L"Service was started successfully!\n");

    }

    else

    {

        wprintf(L"Service not started.\n");

        wprintf(L"  Current State: %d\n", ssStatus.dwCurrentState);

        wprintf(L"  Exit Code: %d\n", ssStatus.dwWin32ExitCode);

        wprintf(L"  Check Point: %d\n", ssStatus.dwCheckPoint);

        wprintf(L"  Wait Hint: %d\n", ssStatus.dwWaitHint);

    }

 

    CloseServiceHandle(schService);

    CloseServiceHandle(schSCManager);

}

 

 

 

 

< Windows Services 14 | Win32 Programming | Windows Services Win32 Programming | Windows Services 16 >