您的位置:首页 > 编程语言 > C语言/C++

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

2015-08-21 09:31 447 查看

概要


服务控制管理器 (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 );

4000
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 );
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息