Windows Services Programming 24

 

 

 

 

 

Another Program Example on How to Stop Windows Service

 

The following program example demonstrates how to programmatically stop a service by first stopping its dependencies. Create a new empty Win32 console application project for new solution. Give a suitable project name and change the project location if needed.

 

Another Program Example on How to Stop Windows Service: Creating new Win32 C++ console application project in Visual C++ .NET

 

Then, add the source file and give it a suitable name.

 

Another Program Example on How to Stop Windows Service: Adding new C++ source file for C++ source code to the existing C++ project

 

Next, add the following source code.

 

//**********************************************************************

//  This program demonstrates how to programmatically stop a service

//  by first stopping its dependencies.

//

//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF

//  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED

//  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A

//  PARTICULAR PURPOSE.

//

//  Copyright (C) 1999 Microsoft Corporation. All rights reserved.

//**********************************************************************

#include <windows.h>

#include <stdio.h>

//**********************************************************************

//  StopService()

//  PURPOSE :     This function attempts to stop a service. It allows

//                the caller to specify whether dependent services

//                should also be stopped. It also allows a timeout

//                value to be passed, to prevent a scenario in which a

//                service shutdown hangs, and in turn the application stopping the service hangs.

//  PARAMETERS:   hSCM - open handle to the service control manager

//                hService - open handle to the service to be stopped

//                fStopDependencies - flag indicating whether to stop dependent services

//                dwTimeout - maximum time (in milliseconds) to wait for the service and its dependencies to stop

//  RETURN VALUE: If the operation is successful, ERROR_SUCCESS is

//                returned. Otherwise, a Win32 error code is returned.

//**********************************************************************

 

DWORD StopService(SC_HANDLE hSCM, SC_HANDLE hService, BOOL fStopDependencies, DWORD dwTimeout)

{

   SERVICE_STATUS ss;

   DWORD dwStartTime = GetTickCount();

 

   // Make sure the service is not already stopped

   if (!QueryServiceStatus( hService, &ss) )

      return GetLastError();

 

   if (ss.dwCurrentState == SERVICE_STOPPED)

      return ERROR_SUCCESS;

 

   // If a stop is pending, just wait for it

   while (ss.dwCurrentState == SERVICE_STOP_PENDING)

   {

      Sleep(ss.dwWaitHint);

      if (!QueryServiceStatus(hService, &ss) )

         return GetLastError();

      if (ss.dwCurrentState == SERVICE_STOPPED)

         return ERROR_SUCCESS;

      if (GetTickCount() - dwStartTime > dwTimeout)

         return ERROR_TIMEOUT;

   }

 

   // If the service is running, dependencies must be stopped first

   if (fStopDependencies)

   {

      DWORD i;

      DWORD dwBytesNeeded;

      DWORD dwCount;

 

      LPENUM_SERVICE_STATUS   lpDependencies = NULL;

      ENUM_SERVICE_STATUS     ess;

      SC_HANDLE               hDepService;

 

      // Pass a zero-length buffer to get the required buffer size

      if (EnumDependentServices( hService, SERVICE_ACTIVE, lpDependencies, 0, &dwBytesNeeded, &dwCount) )

        {

              // If the Enum call succeeds, then there are no dependent services so do nothing

              wprintf(L"There are no dependencies for this service...\n");

      }

        else

        {

         if (GetLastError() != ERROR_MORE_DATA)

            return GetLastError(); // Unexpected error

 

         // Allocate a buffer for the dependencies

         lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);

 

         if ( !lpDependencies )

             {

                   wprintf(L"Buffer allocation for dependencies failed!\n");

                   return GetLastError();

            }

         __try {

 

            // Enumerate the dependencies

            if ( !EnumDependentServices(hService, SERVICE_ACTIVE, lpDependencies, dwBytesNeeded, &dwBytesNeeded, &dwCount) )

               return GetLastError();

                  else

                        wprintf(L"EnumDependentServices() is OK! Stopping the dependencies...\n");

 

            for ( i = 0; i < dwCount; i++ )

                  {

                        wprintf(L"%s service...\n", lpDependencies->lpServiceName);

                        ess = *(lpDependencies + i);

 

               // Open the service

               hDepService = OpenService(hSCM, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);

               if ( !hDepService )

                  return GetLastError();

 

               __try {

                  // Send a stop code

                  if ( !ControlService(hDepService, SERVICE_CONTROL_STOP, &ss) )

                     return GetLastError();

                          else

                                wprintf(L"Stopping %s ...\n", lpDependencies->lpServiceName);

 

                  // Wait for the service to stop

                  while (ss.dwCurrentState != SERVICE_STOPPED)

                          {

                     Sleep( ss.dwWaitHint );

                     if (!QueryServiceStatus(hDepService, &ss) )

                        return GetLastError();

 

                     if (ss.dwCurrentState == SERVICE_STOPPED)

                               {

                                     wprintf(L"Dependencies %s service was stopped successfully!\n", lpDependencies->lpServiceName);

                        break;

                                   

                                    }

 

                     if (GetTickCount() - dwStartTime > dwTimeout)

                        return ERROR_TIMEOUT;

                  }

 

               }

                     __finally

                     {

                  // Always release the service handle

                  CloseServiceHandle( hDepService);

               }

            }

         }

             __finally

             {

            // Always free the enumeration buffer

            HeapFree(GetProcessHeap(), 0, lpDependencies);

         }

      }

   }

 

   // Send a stop code to the main service

   if (!ControlService(hService, SERVICE_CONTROL_STOP, &ss) )

      return GetLastError();

 

   // Wait for the service to stop

   while (ss.dwCurrentState != SERVICE_STOPPED)

   {

      Sleep( ss.dwWaitHint );

      if (!QueryServiceStatus(hService, &ss) )

         return GetLastError();

 

      if (ss.dwCurrentState == SERVICE_STOPPED)

              break;

 

      if (GetTickCount() - dwStartTime > dwTimeout)

         return ERROR_TIMEOUT;

   }

   // Return success

   return ERROR_SUCCESS;

}

 

//**********************************************************************

//  DisplayError()

//  PURPOSE :     This is a helper function to display an error message if a function in wmain() fails.

//  PARAMETERS:   szAPI - the name of the function that failed

//                                 dwError - the Win32 error code indicating why the  function failed//

//  RETURN VALUE: None

//**********************************************************************

 

void DisplayError( LPTSTR szAPI, DWORD dwError )

{

   LPTSTR lpBuffer = NULL;

 

   FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |

         FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,

         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),   (LPTSTR) &lpBuffer, 0, NULL );

 

   wprintf(L"%s failed:\n", szAPI );

   wprintf(L"    error code = %u\n", dwError );

   wprintf(L"    message    = %s\n", lpBuffer );

 

   LocalFree( lpBuffer );

}

 

//**********************************************************************

//  wmain() -- becomes main() for ANSI or wmain() for Unicode

//  PURPOSE :     This is the entry point for the program. This function

//                contains sample code demonstrating how to use the

//                StopService() function implemented above.

//  PARAMETERS:   argc - the number of command-line arguments

//                                  argv[] - an array of command-line arguments

//  RETURN VALUE: None

//**********************************************************************

void wmain(int argc, WCHAR *argv[] )

{

   SC_HANDLE hSCM;

   SC_HANDLE hService;

   DWORD     dwError;

 

   if ( argc < 2 )

   {

      wprintf(L"Usage: \"%s\" <ServiceName>\n", argv[0] );

      return;

   }

 

   __try

   {

      // Open the SCM database

      hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT );

      if ( !hSCM )

        {

         DisplayError(L"OpenSCManager()", GetLastError() );

         __leave;

      }

 

      // Open the specified service

      hService = OpenService( hSCM, argv[1], SERVICE_STOP | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS );

      if ( !hService )

        {

         DisplayError(L"OpenService()", GetLastError() );

         __leave;

      }

 

      // Try to stop the service, specifying a 30 second timeout

      dwError = StopService( hSCM, hService, TRUE, 30000 ) ;

      if ( dwError == ERROR_SUCCESS )

         wprintf(L"The main service, %s was stopped successfully!\n", argv[1] );

      else

         DisplayError(L"StopService()", dwError );

 

   }

   __finally

   {

      if ( hService )

         CloseServiceHandle( hService );

 

      if ( hSCM )

         CloseServiceHandle( hSCM );

   }

}

 

Build the project and make sure there is no error.

We will test the IIS Admin service which having the World Wide Web Publishing service dependency. This can be verified through the IIS Admin Properties page which can be invoked from Windows Services snap-in.

 

Another Program Example on How to Stop Windows Service: The IIS Admin service dependencies

 

Try running the program with iisadmin (service name) service as the argument.

 

Another Program Example on How to Stop Windows Service:A sample console program output in action, stopping Windows Services which has dependencies

 

Then, do a verification using Windows Services snap-in.

 

Another Program Example on How to Stop Windows Service:A sample console program output in action, stopping Windows Services which has dependencies - verify

 

Well, that all folks for this quite long session which covered a complete Windows services programming using Win32. More or 'missing information' can be found at Windows Service Reference.

 

 

 

 

< Windows Services 23 | Win32 Programming | Windows Services Win32 Programming | Windows Exception Handling >