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

来源:互联网 发布:手机店铺销售软件 编辑:程序博客网 时间:2024/05/29 19:54
概要
服务控制管理器 (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 );   }}

0 0