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:如果缓冲区太小,指向接收的需要返回剩余的服务条目的字节数的变量的指针。
返回值:如果此函数成功,返回值不为零。如果函数失败,返回值为零。
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; }