[Win32] SCManager 服务控制管理器API(2)

本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan所有,转载请注明出处: http://blog.csdn.net/zuishikonghuan/article/details/47808805
在上一篇博文“[Win32] SCManager 服务控制管理器API(1)”中(地址: http://blog.csdn.net/zuishikonghuan/article/details/47803033),讲到了打开服务控制管理器、创建服务、打开服务、删除服务、获取服务状态、启动服务、发送控制码,这一篇继续。

9。EnumServicesStatus 枚举服务

BOOL WINAPI EnumServicesStatus(
  _In_        SC_HANDLE             hSCManager,
  _In_        DWORD                 dwServiceType,
  _In_        DWORD                 dwServiceState,
  _Out_opt_   LPENUM_SERVICE_STATUS lpServices,
  _In_        DWORD                 cbBufSize,
  _Out_       LPDWORD               pcbBytesNeeded,
  _Out_       LPDWORD               lpServicesReturned,
  _Inout_opt_ LPDWORD               lpResumeHandle
);

hSCManager:服务控制管理器句柄。此句柄是OpenSCManager函数返回的,并且必须具有 SC_MANAGER_ENUMERATE_SERVICE 访问权限。

dwServiceType:要枚举的服务类型。

SERVICE_DRIVER:SERVICE_KERNEL_DRIVER 和 SERVICE_FILE_SYSTEM_DRIVER。

SERVICE_FILE_SYSTEM_DRIVER:文件系统驱动程序服务。

SERVICE_KERNEL_DRIVER:驱动程序服务。

SERVICE_WIN32:SERVICE_WIN32_OWN_PROCESS 和 SERVICE_WIN32_SHARE_PROCESS。

SERVICE_WIN32_OWN_PROCESS:在他们自己的进程中运行的服务。

SERVICE_WIN32_SHARE_PROCESS:与一个或多个其他服务共享一个进程的服务。
一般为SERVICE_WIN32

dwServiceState:服务要枚举的状态。此参数可以是下列值之一:

SERVICE_ACTIVE:枚举是处于以下状态的服务: SERVICE_START_PENDING、 SERVICE_STOP_PENDING、 SERVICE_RUNNING、SERVICE_CONTINUE_PENDING、 SERVICE_PAUSE_PENDING 和 SERVICE_PAUSED。

SERVICE_INACTIVE:枚举服务处于 SERVICE_STOPPED 状态。

SERVICE_STATE_ALL:SERVICE_ACTIVE 和 SERVICE_INACTIVE。

lpServices:指向包含数组的 ENUM_SERVICE_STATUS 结构,它接收名称服务数据库中的每个服务的状态信息的缓冲区的指针。缓冲区必须足够大以容纳结构,再加上他们的成员所指向的字符串。此数组的最大大小为 256 K 字节。若要确定所需的大小,请为此参数与 cbBufSize 参数置 0。该函数将失败,时出错将返回 ERROR_INSUFFICIENT_BUFFER。PcbBytesNeeded 参数将收到所需的大小。

ENUM_SERVICE_STATUS 结构:

typedef struct _ENUM_SERVICE_STATUS {
  LPTSTR         lpServiceName;
  LPTSTR         lpDisplayName;
  SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUS, *LPENUM_SERVICE_STATUS;

lpServiceName:服务名称

lpDisplayName:显示名称

ServiceStatus:服务状态

SERVICE_STATUS结构见 上一篇 和[Win32] 服务程序开发(1)基本概念和服务程序的框架

cbBufSize:以字节为单位所指向的缓冲区的大小

pcbBytesNeeded:如果缓冲区太小,指向接收的需要返回剩余的服务条目的字节数的变量的指针。

lpServicesReturned:指向一个变量来接收服务项数返回的指针。

lpResumeHandle:一个指针指向的变量的输入,指定枚举的起始点。你必须第一次调用此函数设置此值为零。

返回值:如果此函数成功,返回值不为零。如果函数失败,返回值为零。

10。QueryServiceConfig 获取服务配置参数

BOOL WINAPI QueryServiceConfig(
  _In_      SC_HANDLE              hService,
  _Out_opt_ LPQUERY_SERVICE_CONFIG lpServiceConfig,
  _In_      DWORD                  cbBufSize,
  _Out_     LPDWORD                pcbBytesNeeded
);

hService:务的句柄。此句柄是OpenService 或 CreateService函数返回的,并且它必须具有 SERVICE_QUERY_CONFIG 访问权限。

lpServiceConfig:指向接收服务配置信息的缓冲区的指针。数据的格式是一个 QUERY_SERVICE_CONFIG 结构。

QUERY_SERVICE_CONFIG结构:

typedef struct _QUERY_SERVICE_CONFIG {
  DWORD  dwServiceType;
  DWORD  dwStartType;
  DWORD  dwErrorControl;
  LPTSTR lpBinaryPathName;
  LPTSTR lpLoadOrderGroup;
  DWORD  dwTagId;
  LPTSTR lpDependencies;
  LPTSTR lpServiceStartName;
  LPTSTR lpDisplayName;
} QUERY_SERVICE_CONFIG, *LPQUERY_SERVICE_CONFIG;

dwServiceType:见上一篇中对”Createservice“的介绍。(传送门)

dwStartType:见上一篇中对”Createservice“的介绍。(传送门)

dwErrorControl:见上一篇中对”Createservice“的介绍。(传送门)

lpBinaryPathName:见上一篇中对”Createservice“的介绍。(传送门)

lpLoadOrderGroup:见上一篇中对”Createservice“的介绍。(传送门)

dwTagId:见上一篇中对”Createservice“的介绍。(传送门)

lpDependencies:见上一篇中对”Createservice“的介绍。(传送门)

lpServiceStartName:如果服务类型为 SERVICE_WIN32_OWN_PROCESS 或 SERVICE_WIN32_SHARE_PROCESS,此成员是帐户的服务进程将登录作为运行时的名称。此名称可以是Domain\UserName。如果该帐户属于内置域,名称可以是.\UserName。如果进程运行在本地系统帐户下,名称也可以"LocalSystem"。
如果服务类型为 SERVICE_KERNEL_DRIVER 或 SERVICE_FILE_SYSTEM_DRIVER,此成员是驱动程序对象名称 (即,\FileSystem\Rdr 或 \Driver\Xns),输入和输出 (I/O) 系统使用加载设备驱动程序。如果此成员为 NULL,驱动程序是由 I/O 系统,根据服务名称创建的默认对象名称运行。

lpDisplayName:服务描述。能超过类型为 REG_SZ 注册表值的大小。也可以指定为这样:@[path\]dllname,-strID。请参见MSDN文档的RegLoadMUIString

cbBufSize:以字节为单位的缓冲区的大小

pcbBytesNeeded:如果缓冲区太小,指向接收的需要返回剩余的服务条目的字节数的变量的指针。

返回值:如果此函数成功,返回值不为零。如果函数失败,返回值为零。

11。QueryServiceConfig2 获取服务配置可选参数

BOOL WINAPI QueryServiceConfig2(
  _In_      SC_HANDLE hService,
  _In_      DWORD     dwInfoLevel,
  _Out_opt_ LPBYTE    lpBuffer,
  _In_      DWORD     cbBufSize,
  _Out_     LPDWORD   pcbBytesNeeded
);

hService:服务句柄。此句柄是 OpenService 或 CreateService 函数返回的,并且它必须具有 SERVICE_QUERY_CONFIG 访问权限。

dwInfoLevel:要查询的配置信息。此参数可以是下列值之一:

SERVICE_CONFIG_DELAYED_AUTO_START_INFO:LpInfo 参数是指向 SERVICE_DELAYED_AUTO_START_INFO 结构的指针。Windows Server 2003 和 Windows XP: 不支持此值。

SERVICE_CONFIG_DESCRIPTION:缓冲区参数是指向 SERVICE_DESCRIPTION 结构的指针。

SERVICE_CONFIG_FAILURE_ACTIONS:缓冲区参数是指向 SERVICE_FAILURE_ACTIONS 结构的指针。

SERVICE_CONFIG_FAILURE_ACTIONS_FLAG:LpInfo 参数是指向 SERVICE_FAILURE_ACTIONS_FLAG 结构的指针。Windows Server 2003 和 Windows XP: 不支持此值。

SERVICE_CONFIG_PREFERRED_NODE:LpInfo 参数是指向 SERVICE_PREFERRED_NODE_INFO 结构的指针。Windows Server 2008、 Windows Vista、 Windows Server 2003 和 Windows XP: 不支持此值。

SERVICE_CONFIG_PRESHUTDOWN_INFO:LpInfo 参数是指向 SERVICE_PRESHUTDOWN_INFO 结构的指针。Windows Server 2003 和 Windows XP: 不支持此值。

SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO:LpInfo 参数是指向 SERVICE_REQUIRED_PRIVILEGES_INFO 结构的指针。Windows Server 2003 和 Windows XP: 不支持此值。

SERVICE_CONFIG_SERVICE_SID_INFO:LpInfo 参数是指向 SERVICE_SID_INFO 结构的指针。Windows Server 2003 和 Windows XP: 不支持此值。

SERVICE_CONFIG_TRIGGER_INFO:LpInfo 参数是指向 SERVICE_TRIGGER_INFO 结构的指针。Windows Server 2008、 Windows Vista、 Windows Server 2003 和 Windows XP: 不支持此值。

SERVICE_CONFIG_LAUNCH_PROTECTED:LpInfo 参数是一个 SERVICE_LAUNCH_PROTECTED_INFO 结构的指针。此值从 Windows 8.1 开始支持。

lpBuffer:指向接收服务配置信息的缓冲区的指针。此数据的格式取决于 dwInfoLevel 参数的值。
此数组的最大大小为 8k 字节。若要确定所需的大小,请将此参数与 cbBufSize 参数设置为 0。该函数将失败GetLastError返回 ERROR_INSUFFICIENT_BUFFER。PcbBytesNeeded 参数接收所需的大小。

SERVICE_DESCRIPTION 结构:

typedef struct _SERVICE_DESCRIPTION {
  LPTSTR lpDescription;
} SERVICE_DESCRIPTION, *LPSERVICE_DESCRIPTION;

lpDescription:服务描述。能超过类型为 REG_SZ 注册表值的大小。也可以指定为这样:@[path\]dllname,-strID。请参见MSDN文档的RegLoadMUIString

SERVICE_FAILURE_ACTIONS 结构:

typedef struct _SERVICE_FAILURE_ACTIONS {
  DWORD     dwResetPeriod;
  LPTSTR    lpRebootMsg;
  LPTSTR    lpCommand;
  DWORD     cActions;
  SC_ACTION *lpsaActions;
} SERVICE_FAILURE_ACTIONS, *LPSERVICE_FAILURE_ACTIONS;
dwResetPeriod:以秒为单位,表示服务失败计数在没有错误下重置的时间,INFINITE表示永远不会被重置
lpRebootMsg:要重新启动 SC_ACTION_REBOOT 服务控制器动作响应之前广播到服务器的用户的消息。对于修改配置,如果此值为 NULL,重新启动消息是不变的。如果值为空字符串 (""),重新启动消息将被删除并没有消息被广播。
lpCommand:响应 SC_ACTION_RUN_COMMAND 时执行进程的命令行。这一过程在相同的服务帐户下运行。对于修改配置,如果此值为 NULL,该命令是不变的。如果值为空字符串 (""),该命令删除并且服务失败时不运行任何程序。
cActions:LpsaActions 数组中的元素数。对于修改配置,如果此值为 0,但 lpsaActions 不是 NULL,删除重置期间和失败操作的数组。
lpsaActions:指向一个 SC_ACTION 结构数组的指针。对于修改配置,如果此值为 NULL,则忽略,cActions 和 dwResetPeriod 的成员。
SC_ACTION 结构:
typedef struct _SC_ACTION {
  SC_ACTION_TYPE Type;
  DWORD          Delay;
} SC_ACTION, *LPSC_ACTION;
Type:要执行的操作。此成员可以是下列之一:
SC_ACTION_NONE:没有行动。

SC_ACTION_REBOOT:重新启动计算机。

SC_ACTION_RESTART:重新启动该服务。

SC_ACTION_RUN_COMMAND:运行一个命令。
Delay:在执行指定的操作,以毫秒为单位之前等待的时间。
备注:服务启动失败时,系统启动的次数进行计数。经过 dwResetPeriod 秒时,计数重置为 0。当服务失败第 n 次时,服务控制器执行 lpsaActions 数组中的元素 [N-1] 中指定的操作。如果 N 大于 cActions,服务控制器重复上次操作数组中。

cbBufSize:以字节为单位的缓冲区的大小

pcbBytesNeeded:如果缓冲区太小,指向接收的需要返回剩余的服务条目的字节数的变量的指针。

返回值:如果此函数成功,返回值不为零。如果函数失败,返回值为零。

12。ChangeServiceConfig 修改服务配置参数

BOOL WINAPI ChangeServiceConfig(
  _In_      SC_HANDLE hService,
  _In_      DWORD     dwServiceType,
  _In_      DWORD     dwStartType,
  _In_      DWORD     dwErrorControl,
  _In_opt_  LPCTSTR   lpBinaryPathName,
  _In_opt_  LPCTSTR   lpLoadOrderGroup,
  _Out_opt_ LPDWORD   lpdwTagId,
  _In_opt_  LPCTSTR   lpDependencies,
  _In_opt_  LPCTSTR   lpServiceStartName,
  _In_opt_  LPCTSTR   lpPassword,
  _In_opt_  LPCTSTR   lpDisplayName
);

hService:服务句柄。此句柄是OpenService 或 CreateService函数返回的,并且必须具有 SERVICE_CHANGE_CONFIG 访问权限。

从 dwServiceType 到 lpServiceStartName :参见上面的QUERY_SERVICE_CONFIG结构(快速跳转)

lpPassword:LpServiceStartName 参数所指定的帐户名称的密码。如果您不更改现有的密码,请指定 NULL。如果该帐户没有密码,或在本地、 网络服务或本地系统帐户运行该服务,请指定空字符串。

lpDisplayName:服务描述。能超过类型为 REG_SZ 注册表值的大小。也可以指定为这样:@[path\]dllname,-strID。请参见MSDN文档的RegLoadMUIString

返回值:如果此函数成功,返回值不为零。如果函数失败,返回值为零。

13。ChangeServiceConfig2 修改服务配置可选参数

BOOL WINAPI ChangeServiceConfig2(
  _In_     SC_HANDLE hService,
  _In_     DWORD     dwInfoLevel,
  _In_opt_ LPVOID    lpInfo
);

hService:服务的句柄。此句柄是OpenService 或 CreateService函数返回的,并且必须具有 SERVICE_CHANGE_CONFIG 访问权限。

dwInfoLevel:见上面QueryServiceConfig2的相关内容(快速跳转)

lpInfo:见上面QueryServiceConfig2的相关内容(快速跳转)

返回值:如果此函数成功,返回值不为零。如果函数失败,返回值为零。

 示例源码:
参数说明和代码注释就不写了,如果看过上文理解下面的很轻松。
①枚举服务
BOOL WINAPI ListWin32Service(){
	SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
	if (hSCManager != NULL){
		DWORD BytesNeeded;
		DWORD count;
		EnumServicesStatus(hSCManager, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &BytesNeeded, &count, 0);
		char* buffer = new char[BytesNeeded];
		RtlZeroMemory(buffer, BytesNeeded);
		ENUM_SERVICE_STATUS* Services = (ENUM_SERVICE_STATUS*)buffer;
		if (EnumServicesStatus(hSCManager, SERVICE_WIN32, SERVICE_STATE_ALL, Services, BytesNeeded, &BytesNeeded, &count, 0)){
			for (int i = 0; i < count; i++) _putts(Services[i].lpServiceName);
			delete[] buffer;
			return TRUE;
		}
		delete[] buffer;
		CloseServiceHandle(hSCManager);
		return FALSE;
	}
	else return FALSE;
}

②修改服务描述
BOOL WINAPI SetServiceDescription(LPCTSTR ServiceName, LPTSTR Description){
	SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
	if (hSCManager != NULL){
		SC_HANDLE hService = OpenService(hSCManager, ServiceName, SERVICE_CHANGE_CONFIG);
		if (hService != NULL){
			SERVICE_DESCRIPTION desc;
			desc.lpDescription = Description;
			if (ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &desc))
			{
				CloseServiceHandle(hService);
				CloseServiceHandle(hSCManager);
				return TRUE;
			}
			CloseServiceHandle(hService);
			CloseServiceHandle(hSCManager);
			return FALSE;
		}
		CloseServiceHandle(hSCManager);
		return FALSE;
	}
	else return FALSE;
}

③让服务启动失败后总是恢复
BOOL WINAPI LetServiceAlwaysReboot(LPCTSTR ServiceName){
	SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
	if (hSCManager != NULL){
		SC_HANDLE hService = OpenService(hSCManager, ServiceName, SC_MANAGER_ALL_ACCESS);//值得一提的是需要用SC_MANAGER_ALL_ACCESS
		if (hService != NULL){
			SERVICE_FAILURE_ACTIONS failact = { 0 };
			SC_ACTION act[3];
			act[0].Delay = act[1].Delay = act[2].Delay = 0;
			act[0].Type = act[1].Type = act[2].Type = SC_ACTION_RESTART;
			failact.cActions = 3;
			failact.lpsaActions = act;
			failact.dwResetPeriod = 0;
			if (ChangeServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, &failact))
			{
				CloseServiceHandle(hService);
				CloseServiceHandle(hSCManager);
				return TRUE;
			}
			CloseServiceHandle(hService);
			CloseServiceHandle(hSCManager);
			return FALSE;
		}
		CloseServiceHandle(hSCManager);
		return FALSE;
	}
	else return FALSE;
}




你可能感兴趣的:(Win32,windows,api,winapi)