Windows系统程序设计之系统服务

【作者】北极星2003
【来源】看雪技术论坛(bbs.pediy.com)
【时间】2006-7-18 
【附件】servicemanager.rar

WIN32服务管理器
1.设计目标
  设计简易的Win32服务管理器,实现基本的WIN32服务管理功能,包括启动、停止、添加、删除、暂停、恢复和设置自动、手动、禁用启动类型。

2.设计思路

 
设计思路比较简单:
  (1)枚举服务
  (2)服务控制(启动、停止……)
  (3)排序(枚举出来的服务的以服务名排序的,而系统默认的服务管理是以显示名称排序的)
3.难点
  (1)需要注意 OpenSCManager 时权限设置
  (2)在对ENUM_SERVICE_STATUS结构数组进行排序时并不能直接对其本身进行排序,需要建立一个相应的索引数组。(这里使用插入排序算法)

4.详细设计
// CSM.h

代码:
#ifndef _CSM_H #define _CSM_H #ifndef _WINSVC_H #include <Winsvc.h> #define _WINSVC_H #endif #include <stdlib.h> const int MAX_SERVICE_NUM = 512 ; class CSM { public:   DWORD    dwSerNum ;   UINT    nSerIndex[MAX_SERVICE_NUM];   ENUM_SERVICE_STATUS SerStatus[MAX_SERVICE_NUM] ; public:   CSM () {}   ~CSM () {}    public:   // 枚举服务   BOOL EnumWin32Service ( ) ;      // 启动服务   BOOL StartWin32Service ( UINT nIndex ) ;      // 停止服务   BOOL StopWin32Service ( UINT nIndex ) ;      // 暂停服务   BOOL PauseWin32Service ( UINT nIndex ) ;      //恢复服务   BOOL ContinueWin32Service ( UINT nIndex ) ;      // 服务启动类型--自动   BOOL SetAutoStartType ( UINT nIndex ) ;   // 服务启动类型--手动   BOOL SetManualStartType ( UINT nIndex ) ;   // 服务启动类型--禁用   BOOL SetDisableStartType ( UINT nIndex ) ;   // 取得服务的启动类型   UINT GetServiceStartType ( UINT nIndex ) ;      // 加载服务   BOOL AddWin32Service ( LPCSTR lpServiceName, LPCSTR lpDisplayName, LPSTR lpPathName ) ;   // 卸载服务   BOOL DeleteWin32Service ( UINT nIndex ) ;    protected:   // 取得指定索引的服务的句柄   SC_HANDLE GetServiceByIndex ( UINT nIndex ) ;   // 以显示名称排序   void SortByDisplayName () ;   // 自定义字符串比较   int MyStrCmp ( LPSTR FirStr, LPSTR SecStr ) ; } ; #endif



//CSM.cpp

代码:
#include "stdafx.h" #include "CSM.h" // 枚举服务 BOOL CSM::EnumWin32Service ( ) {   SC_HANDLE hSCManager = OpenSCManager ( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE|GENERIC_READ ) ;   if ( hSCManager == NULL )   {     return FALSE ;   }        DWORD dwBufSize = 512 * sizeof(ENUM_SERVICE_STATUS) ;     DWORD dwBytesNeeded, lpResumeHandle = 0 ;   if ( !EnumServicesStatus(hSCManager, SERVICE_WIN32, SERVICE_STATE_ALL, \     SerStatus, dwBufSize, &dwBytesNeeded, &dwSerNum, &lpResumeHandle ) )   {     return FALSE ;   }      SortByDisplayName () ;   CloseServiceHandle ( hSCManager ) ;   return TRUE ; } // 启动服务 BOOL CSM::StartWin32Service ( UINT nIndex ) {   SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;   if ( !StartService ( hSCService, 0, NULL ) )   {     CloseServiceHandle ( hSCService ) ;      return FALSE ;   }      CloseServiceHandle ( hSCService ) ;    return TRUE ; } // 停止服务 BOOL CSM::StopWin32Service ( UINT nIndex ) {   SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;   if ( !ControlService ( hSCService, SERVICE_CONTROL_STOP, &(SerStatus[nIndex].ServiceStatus) ) )   {     CloseServiceHandle ( hSCService ) ;      return FALSE ;   }      CloseServiceHandle ( hSCService ) ;    return TRUE ; } // 暂停服务 BOOL CSM::PauseWin32Service ( UINT nIndex ) {   SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;   if ( !ControlService ( hSCService, SERVICE_CONTROL_PAUSE, &(SerStatus[nIndex].ServiceStatus) ) )   {     CloseServiceHandle ( hSCService ) ;      return FALSE ;   }      CloseServiceHandle ( hSCService ) ;    return TRUE ; } //恢复服务 BOOL CSM::ContinueWin32Service ( UINT nIndex ) {   SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;   if ( !ControlService ( hSCService, SERVICE_CONTROL_CONTINUE, &(SerStatus[nIndex].ServiceStatus) ) )   {     CloseServiceHandle ( hSCService ) ;      return FALSE ;   }      CloseServiceHandle ( hSCService ) ;    return TRUE ; } // 服务启动类型--自动 BOOL CSM::SetAutoStartType ( UINT nIndex ) {   SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;   if ( !ChangeServiceConfig( hSCService, SERVICE_NO_CHANGE, \     SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)  )   {     CloseServiceHandle ( hSCService ) ;      return FALSE ;   }      CloseServiceHandle ( hSCService ) ;    return TRUE ; } // 服务启动类型--手动 BOOL CSM::SetManualStartType ( UINT nIndex ) {   SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;   if ( !ChangeServiceConfig( hSCService, SERVICE_NO_CHANGE, \     SERVICE_DEMAND_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)  )   {     CloseServiceHandle ( hSCService ) ;      return FALSE ;   }      CloseServiceHandle ( hSCService ) ;    return TRUE ; } // 服务启动类型--禁用 BOOL CSM::SetDisableStartType ( UINT nIndex ) {   SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;   if ( !ChangeServiceConfig( hSCService, SERVICE_NO_CHANGE, \     SERVICE_DISABLED, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL)  )   {     CloseServiceHandle ( hSCService ) ;      return FALSE ;   }      CloseServiceHandle ( hSCService ) ;    return TRUE ; }   // 取得服务的启动类型 UINT CSM::GetServiceStartType ( UINT nIndex ) {   SC_HANDLE hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;      LPQUERY_SERVICE_CONFIG lpServiceConfig = (LPQUERY_SERVICE_CONFIG)new BYTE[1024] ;   DWORD dwByteNeeded ;   if ( !QueryServiceConfig ( hSCService, lpServiceConfig, 1024, &dwByteNeeded ) )   {     CloseServiceHandle ( hSCService ) ;      return 0 ;   }      UINT nServiceType = 0 ;   switch ( lpServiceConfig->dwStartType )   {   case SERVICE_AUTO_START:  nServiceType = 1 ;  break ;   case SERVICE_DEMAND_START:  nServiceType = 2 ;  break ;   case SERVICE_DISABLED:    nServiceType = 3 ;  break ;   default:          nServiceType = 4 ;   }      CloseServiceHandle ( hSCService ) ;    delete lpServiceConfig ;   return nServiceType ; } // 加载服务 BOOL CSM::AddWin32Service ( LPCSTR lpServiceName, LPCSTR lpDisplayName, LPSTR lpPathName ) {   SC_HANDLE hSCManager = OpenSCManager ( NULL, NULL, SC_MANAGER_CREATE_SERVICE ) ;   if ( hSCManager == NULL )   {     return FALSE ;   }      SC_HANDLE hSCService =  CreateService ( hSCManager, lpServiceName, lpDisplayName, \     SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, \     SERVICE_ERROR_NORMAL, lpPathName, NULL, NULL, NULL, NULL, NULL );   if ( hSCService == NULL )   {     DWORD dwErrorCode = GetLastError () ;     CloseServiceHandle ( hSCManager ) ;     return FALSE ;   }      CloseServiceHandle ( hSCService ) ;   CloseServiceHandle ( hSCManager ) ;   return TRUE ; } // 卸载服务 BOOL CSM::DeleteWin32Service ( UINT nIndex ) {   SC_HANDLE  hSCService = GetServiceByIndex ( nSerIndex[nIndex] ) ;   BOOL    bRet = DeleteService ( hSCService ) ;   DWORD    dwErrorCode = GetLastError () ;   CloseServiceHandle ( hSCService ) ;   return bRet ; } // 取得指定索引的服务的句柄 SC_HANDLE CSM::GetServiceByIndex ( UINT nIndex ) {   SC_HANDLE hSCManager = OpenSCManager ( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE|GENERIC_READ ) ;   if ( hSCManager == NULL )   {     return NULL ;   }      SC_HANDLE hSCService = OpenService ( hSCManager, SerStatus[nIndex].lpServiceName, SERVICE_ALL_ACCESS ) ;   CloseServiceHandle ( hSCManager ) ;   return hSCService ;   } // 以显示名称排序 void CSM::SortByDisplayName () {   memset ( nSerIndex, 0, sizeof(nSerIndex) ) ;      for ( int i = 1; i < dwSerNum; i++ )   {     for ( int j = i-1; j >= 0; j-- )     {       if ( MyStrCmp ( SerStatus[i].lpDisplayName, SerStatus[nSerIndex[j]].lpDisplayName ) > 0 )         break ;       else         nSerIndex[j+1] = nSerIndex[j] ;     }     nSerIndex[j+1] = i ;   } } // 自定义字符串比较 int CSM::MyStrCmp ( LPSTR FirStr, LPSTR SecStr ) {   char ChA, ChB ;   UINT nIndex = 0 ;      while ( true )   {     ChA = FirStr[nIndex] > 'Z' ? ( FirStr[nIndex] - 0x20 ) : FirStr[nIndex] ;     ChB = SecStr[nIndex] > 'Z' ? ( SecStr[nIndex] - 0x20 ) : SecStr[nIndex] ;          if ( ChA == '\0' && ChB == '\0' )       return 0 ;     else if ( ChA == '\0' )       return -1 ;     else if ( ChB == '\0' )       return 1 ;          if ( ChA > ChB )       return 1 ;     else if ( ChA < ChB )       return -1 ;          nIndex++ ;   }    }



5.遇到的困难
  这个软件相对比较简单,需要注意的是建立索引后的排序。

6.总结(心得)
  增进对WIN32服务管理方式的了解。原本还想写个服务,由于最近较忙且资料实在太多就不写了。在参考文献中列举了一些关于服务的比较优秀的文章,其中还有相应的源代码可以下载。

【参考文献】
[1]. Beginner’s introductory guide to writing, installing, starting, stopping NT services
     http://www.codeproject.com/system/serviceskeleton.asp
[2]. CServiceHelper
     http://www.codeproject.com/system/cservicehelper.asp
[3]. Kmd教程2-服务
     http://211.90.241.130:22366/view.asp?file=321
[4]. Wind32位程序设计初步之服务
     http://www.webstudy8.com/web/net/209/0651108404367523.asp

【版权声明】必须注明原创于看雪技术论坛(bbs.pediy.com) 及作者,并保持文章的完整性。