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 ); } }
相关文章推荐
- 如何重装TCP/IP协议
- Windows 8 官方高清壁纸欣赏与下载
- 谁是桌面王者?Win PK Linux三大镇山之宝
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- 应用领航:盘点那些年我们一起追过的OS
- Windows Clang开发环境备忘
- 从Windows系统下访问Linux分区相关软件
- 无奇不有!盘点各国自己开发的操作系统
- 肯特·贝克:改变人生的代码整理魔法
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- 你应该学习哪种编程语言?
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得
- [转]我们需要一种其他人能使用的编程语言
- 微软镜像下载
- windows server域用户提升到本地更高权限组中的方法
- 使用命令修改注册表键值及权限
- 通过手机、电脑远程开关机,Windows和linux机手机,电脑相互控制