C++停止服务及其依赖项

概要
服务控制管理器 (SCM) 不会尝试停止服务,如果其他正在运行的服务依赖于它。若要以编程方式停止此类服务,必须首先枚举并停止其依赖项。本文的"更多信息"部分中的示例代码演示如何使用 EnumDependentServices() API 来停止该服务。
详细信息
时到 scm 服务数据库中注册服务,还建立及其依赖项。SCM 可以保证依赖项将自动启动的服务本身开始之前。

可以通过将 SERVICE_CONTROL_STOP 请求发送到服务通过 SCM ControlService() API 通过停止服务。如果 SCM 收到 SERVICE_CONTROL_STOP 请求服务时,它指示服务停止通过转发 stop 代码服务的ServiceMain()功能才能正常工作。但是,如果 SCM 确定其他正在运行的服务都依赖于指定的服务,它将不会转发停止请求。相反,它将返回错误代码 1051 (ERROR_DEPENDENT_SERVICES_RUNNING) —"停止控制已发送给其他正在运行的服务依赖的服务。"

示例代码

下面的代码实现一个StopService()函数,还可以尝试停止指定的服务相关性。
//**********************************************************************
// 
//  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 <tchar.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

      } 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 )
            return GetLastError();

         __try {

            // Enumerate the dependencies
            if ( !EnumDependentServices( hService, SERVICE_ACTIVE, 
                  lpDependencies, dwBytesNeeded, &dwBytesNeeded,
                  &dwCount ) )
               return GetLastError();

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

               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();

                  // 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 )
                        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 _tmain() 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 );

   _tprintf( TEXT("%s failed:\n"), szAPI );
   _tprintf( TEXT("    error code = %u\n"), dwError );
   _tprintf( TEXT("    message    = %s\n"), lpBuffer );

   LocalFree( lpBuffer );
}


//**********************************************************************
// 
//  _tmain() -- 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 _tmain( int argc, TCHAR *argv[] ) {

   SC_HANDLE hSCM;
   SC_HANDLE hService;
   DWORD     dwError;

   if ( argc < 2 ) {
      _tprintf( TEXT("usage: \"%s\" <ServiceName>\n"), argv[0] );
      return;
   }

   __try {

      // Open the SCM database
      hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT );
      if ( !hSCM ) {
         DisplayError( TEXT("OpenSCManager()"), GetLastError() );
         __leave;
      }

      // Open the specified service
      hService = OpenService( hSCM, argv[1], SERVICE_STOP
            | SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS );
      if ( !hService ) {
         DisplayError( TEXT("OpenService()"), GetLastError() );
         __leave;
      }

      // Try to stop the service, specifying a 30 second timeout
      dwError = StopService( hSCM, hService, TRUE, 30000 ) ;
      if ( dwError == ERROR_SUCCESS )
         _tprintf( TEXT("Service stopped.\n") );
      else
         DisplayError( TEXT("StopService()"), dwError );

   } __finally {

      if ( hService )
         CloseServiceHandle( hService );

      if ( hSCM )
         CloseServiceHandle( hSCM );
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值