Windows开发——管理系统服务
¶创建删除
¶CreateService
-
用途
创建服务对象并将其添加到指定的服务控制管理器数据库。 -
语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15SC_HANDLE CreateServiceA(
[in] SC_HANDLE hSCManager,
[in] LPCSTR lpServiceName,
[in, optional] LPCSTR lpDisplayName,
[in] DWORD dwDesiredAccess,
[in] DWORD dwServiceType,
[in] DWORD dwStartType,
[in] DWORD dwErrorControl,
[in, optional] LPCSTR lpBinaryPathName,
[in, optional] LPCSTR lpLoadOrderGroup,
[out, optional] LPDWORD lpdwTagId,
[in, optional] LPCSTR lpDependencies,
[in, optional] LPCSTR lpServiceStartName,
[in, optional] LPCSTR lpPassword
); -
返回值
如果函数成功,则返回值是服务的句柄。
如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError -
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53int CreateMyService(SC_HANDLE* scm, SC_HANDLE* myservice)
{
/* 创建一个自启动服务 */
SC_HANDLE service = NULL;
std::wstring ServiceName = L"Jiege Service";
std::wstring ShowServiceName = L"Jiege";
DWORD dwError = 0;
service = OpenService(*scm, ServiceName.c_str(), SERVICE_ALL_ACCESS);
if (service != NULL) /* 服务已存在 */
{
dwError = GetLastError();
LOG_ERROR("OpenService error: {0}.", dwError);
if (!DeleteService(service))
{
dwError = GetLastError();
LOG_ERROR("DeleteService error: {0}.", dwError);
::CloseServiceHandle(service);
return -1;
}
::CloseServiceHandle(service);
return -1;
}
else
{
service = CreateService(*scm,
ServiceName.c_str(),
ShowServiceName.c_str(),
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
L"F:/myproject/JiegeService/JiegeService.EXE",
0, 0, 0, 0, 0);
if (!(service))
{
dwError = GetLastError();
LOG_ERROR("CreateService error: {0}.", dwError);
return -1;
}
*myservice = service;
}
return 0;
}
¶DeleteService
-
用途
标记要从服务控制管理器数据库中删除的指定服务。 -
语法
1
2
3BOOL DeleteService(
[in] SC_HANDLE hService
); -
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。
服务控制管理器可以设置以下错误代码。 其他函数可能由服务控制管理器调用的注册表函数设置。返回代码 说明 ERROR_ACCESS_DENIED 句柄没有 DELETE 访问权限。 ERROR_INVALID_HANDLE 指定的句柄无效。 ERROR_SERVICE_MARKED_FOR_DELETE 指定的服务已被标记为要删除。 -
示例
1
2
3
4
5
6
7
8
9
10
11if (!DeleteService(service))
{
LOG_ERROR("DeleteService error.");
::CloseServiceHandle(scm);
return -1;
}
else {
printf("DeleteService success.\n");
}
::CloseServiceHandle(scm);
¶枚举信息
¶EnumServicesStatus
-
用途
枚举指定服务控制管理器数据库中的服务。 提供了每个服务的名称和状态。
此函数已被 EnumServicesStatusEx)函数取代。 它返回相同的信息 EnumServicesStatus 返回,以及进程标识符和服务的其他信息。 此外, EnumServicesStatusEx 使你可以枚举属于指定组的服务。 -
语法
1
2
3
4
5
6
7
8
9
10BOOL EnumServicesStatusA(
[in] SC_HANDLE hSCManager,
[in] DWORD dwServiceType,
[in] DWORD dwServiceState,
[out, optional] LPENUM_SERVICE_STATUSA lpServices,
[in] DWORD cbBufSize,
[out] LPDWORD pcbBytesNeeded,
[out] LPDWORD lpServicesReturned,
[in, out, optional] LPDWORD lpResumeHandle
); -
ENUM_SERVICE_STATUSA结构
1
2
3
4
5typedef
LPSTR lpServiceName;
LPSTR lpDisplayName;
SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUSA, *LPENUM_SERVICE_STATUSA;结构中包含服务名称,显示名称,启动状态.
-
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。 可能会返回以下错误。返回代码 说明 ERROR_ACCESS_DENIED 句柄没有SC_MANAGER_ENUMERATE_SERVICE 访问权限。 ERROR_MORE_DATA 缓冲区太小。 并非所有活动数据库中的数据都可以返回。tbBytesNeeded 参数包含接收剩余条目所需的字节数。 ERROR_INVALID_PARAMETER 使用了非法参数值。 ERROR_INVALID_HANDLE 该句柄无效。 ERROR_INVALID_LEVEL InfoLevel 参数包含不受支持的值。 ERROR_SHUTDOWN_IN_PROGRESS 系统正在关闭;无法调用此函数。 -
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23LPENUM\_SERVICE\_STATUS lpServices = NULL;
DWORD nSize = 0;
DWORD n;
DWORD nResumeHandle = 0;
lpServices = (LPENUM\_SERVICE\_STATUS) LocalAlloc(LPTR, 64 \* 1024);
EnumServicesStatus(scm,SERVICE\_WIN32,
SERVICE\_STATE\_ALL,
(LPENUM\_SERVICE\_STATUS)lpServices,
64 * 1024,
&nSize,
&n,
&nResumeHandle);
for ( i = 0; i < n; i++)
{
printf("服务名称: %s",lpServices[i].lpServiceName);
printf("显示名称: %s",lpServices[i].lpDisplayName);
if ( lpServices[i].ServiceStatus.dwCurrentState!=SERVICE\_STOPPED)
{
printf("启动状态: 已启动/n");
}
}
¶EnumServicesStatusEx
-
用途
枚举指定服务控制管理器数据库中的服务。 提供每个服务的名称和状态,以及基于指定信息级别的其他数据。 -
语法
1
2
3
4
5
6
7
8
9
10
11
12BOOL EnumServicesStatusExA(
[in] SC_HANDLE hSCManager,
[in] SC_ENUM_TYPE InfoLevel,
[in] DWORD dwServiceType,
[in] DWORD dwServiceState,
[out, optional] LPBYTE lpServices,
[in] DWORD cbBufSize,
[out] LPDWORD pcbBytesNeeded,
[out] LPDWORD lpServicesReturned,
[in, out, optional] LPDWORD lpResumeHandle,
[in, optional] LPCSTR pszGroupName
); -
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。 可能会返回以下错误。返回代码 说明 ERROR_ACCESS_DENIED 句柄没有SC_MANAGER_ENUMERATE_SERVICE 访问权限。 ERROR_MORE_DATA 缓冲区太小。 并非所有活动数据库中的数据都可以返回。tbBytesNeeded 参数包含接收剩余条目所需的字节数。 ERROR_INVALID_PARAMETER 使用了非法参数值。 ERROR_INVALID_HANDLE 该句柄无效。 ERROR_INVALID_LEVEL InfoLevel 参数包含不受支持的值。 ERROR_SHUTDOWN_IN_PROGRESS 系统正在关闭;无法调用此函数。
¶QueryServiceConfig
-
用途
检索指定服务的配置参数。 -
语法
1
2
3
4
5
6BOOL QueryServiceConfigA(
[in] SC_HANDLE hService,
[out, optional] LPQUERY_SERVICE_CONFIGA lpServiceConfig,
[in] DWORD cbBufSize,
[out] LPDWORD pcbBytesNeeded
); -
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。
服务控制管理器可以设置以下错误代码。 其他可由服务控制管理器调用的注册表函数设置。返回代码 说明 ERROR_ACCESS_DENIED 句柄没有SERVICE_QUERY_CONFIG访问权限。 ERROR_INSUFFICIENT_BUFFER 服务配置信息比lpServiceConfig 缓冲区更适合。 获取所有信息所需的字节数在 tbBytesNeededed 参数中返回。 不写入 lpServiceConfig。 ERROR_INVALID_HANDLE 指定的句柄无效。 -
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22LPQUERY\_SERVICE\_CONFIG ServicesInfo = NULL;
for ( i = 0; i < n; i++)
{
SC_HANDLE service = NULL;
DWORD nResumeHandle = 0;
service=OpenService(scm,lpServices[i].lpServiceName,SERVICE_ALL_ACCESS);
ServicesInfo = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 64 \* 1024); //注意分配足够的空间
QueryServiceConfig(service,ServicesInfo,64 \* 1024,&nResumeHandle); //枚举各个服务信息
printf("程序路径: %s",ServicesInfo->lpBinaryPathName);
if(2==ServicesInfo->dwStartType) //启动方式
{
printf("自动/n");
}
if(3==ServicesInfo->dwStartType) {
printf("手动/n");
}
if(4==ServicesInfo->dwStartType)
{
printf("禁止/n");
}
¶配置权限
¶openSCManager
-
用途
建立与指定计算机上的服务控制管理器的连接,并打开指定的服务控制管理器数据库。 -
语法
1
2
3
4
5SC_HANDLE OpenSCManagerA(
[in, optional] LPCSTR lpMachineName,
[in, optional] LPCSTR lpDatabaseName,
[in] DWORD dwDesiredAccess
); -
返回值
如果函数成功,则返回值是指定服务控制管理器数据库的句柄。
如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用GetLastError。
SCM 可以设置以下错误代码。 其他错误代码可由 SCM 调用的注册表函数设置。返回代码 描述 ERROR_ACCESS_DENIED 请求的访问被拒绝。 ERROR_DATABASE_DOES_NOT_EXIST 指定的数据库不存在。 -
示例
以完全权限打开:1
2
3
4
5SC_HANDLE scm;
if((scm = openSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS)==NULL)
{
printf("OpenSCManager Error/n");
}
¶openService
[openService](openServiceA 函数 (winsvc.h) - Win32 apps | Microsoft Learn)
-
用途
打开现有服务。 -
语法
1
2
3
4
5SC_HANDLE OpenServiceA(
[in] SC_HANDLE hSCManager,
[in] LPCSTR lpServiceName,
[in] DWORD dwDesiredAccess
); -
返回值
如果函数成功,则返回值是服务的句柄。
如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。
服务控制管理器可以设置以下错误代码。 其他函数可由服务控制管理器调用的注册表函数设置。返回代码 描述 ERROR_ACCESS_DENIED 句柄无权访问服务。 ERROR_INVALID_HANDLE 指定的句柄无效。 ERROR_INVALID_NAME 指定的服务名称无效。 ERROR_SERVICE_DOES_NOT_EXIST 指定的服务不存在。 -
示例
以完全权限打开1
2
3
4
5SC_HANDLE service;
if(!(service=OpenService(scm,ServerName,SERVICE\_ALL\_ACCESS)))
{
printf("OpenService error!/n");
}
¶启动停止
¶startService
-
用途
启动服务 -
语法
1
2
3
4
5BOOL StartServiceA(
[in] SC_HANDLE hService,
[in] DWORD dwNumServiceArgs,
[in, optional] LPCSTR *lpServiceArgVectors
); -
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。
¶ControlService
-
用途
将控制代码发送到服务。 -
语法
1
2
3
4
5BOOL ControlService(
[in] SC_HANDLE hService,
[in] DWORD dwControl,
[out] LPSERVICE_STATUS lpServiceStatus
); -
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。
¶更改启动方式
¶ChangeServiceConfig
-
用途
更改服务的配置参数 -
语法
1
2
3
4
5
6
7
8
9
10
11
12
13BOOL ChangeServiceConfigA(
[in] SC_HANDLE hService,
[in] DWORD dwServiceType,
[in] DWORD dwStartType,
[in] DWORD dwErrorControl,
[in, optional] LPCSTR lpBinaryPathName,
[in, optional] LPCSTR lpLoadOrderGroup,
[out, optional] LPDWORD lpdwTagId,
[in, optional] LPCSTR lpDependencies,
[in, optional] LPCSTR lpServiceStartName,
[in, optional] LPCSTR lpPassword,
[in, optional] LPCSTR lpDisplayName
); -
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。