SetServiceStatus 函数 (winsvc.h)
汇报调用服务的服务控制管理器的状态信息。
语法
BOOL SetServiceStatus(
[in] SERVICE_STATUS_HANDLE hServiceStatus,
[in] LPSERVICE_STATUS lpServiceStatus
);
参数
[in] hServiceStatus
当前服务的状态信息结构的句柄。 此句柄由 RegisterServiceCtrlHandlerEx 函数返回。
[in] lpServiceStatus
指向 SERVICE_STATUS 结构的指针包含调用服务的最新状态信息。
返回值
如果该函数成功,则返回值为非零值。
如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。
服务控制管理器可以设置以下错误代码。 其他错误代码可由服务控制管理器调用的注册表函数设置。
返回代码 | 说明 |
---|---|
|
指定的服务状态结构无效。 |
|
指定的句柄无效。 |
注解
ServiceMain 函数首先调用 RegisterServiceCtrlHandlerEx 函数以获取服务的SERVICE_STATUS_HANDLE。 然后,它会立即调用 SetServiceStatus 函数,以通知服务控制管理器其状态为SERVICE_START_PENDING。 在初始化期间,服务可以提供更新的状态,以指示它正在取得进展,但它需要更多的时间。 一个常见的 bug 是服务让main线程执行初始化,而单独的线程继续调用 SetServiceStatus 以防止服务控制管理器将其标记为挂起。 但是,如果main线程挂起,则服务启动会以无限循环结束,因为工作线程继续报告main线程正在取得进展。
处理控制请求后,如果服务状态发生更改,则服务的 Handler 函数必须调用 SetServiceStatus ,以便向服务控制管理器报告其新状态。 仅在服务正在更改状态时(例如,在处理停止或关闭控件时)时才需要这样做。 服务还可以随时从服务的任何线程使用此函数,以通知服务控制管理器状态更改,例如,服务何时必须因可恢复错误而停止。
服务只有在调用 RegisterServiceCtrlHandlerEx 以获取服务状态句柄后,才能调用此函数。
如果服务调用 SetServiceStatus 且 dwCurrentState 成员设置为 SERVICE_STOPPED, 而 dwWin32ExitCode 成员设置为非零值,则会将以下条目写入系统事件日志:
Event ID = 7023
Source = Service Control Manager
Type = Error
Description = <ServiceName> terminated with the following error:
<ExitCode>.
以下是调用此函数时的最佳做法:
- 初始化SERVICE_STATUS结构中的所有字段,确保挂起状态具有有效的检查点和等待提示值。 使用合理的等待提示。
- 当状态为SERVICE_START_PENDING或服务可能会崩溃时,请勿注册以接受控件。 初始化完成后,接受SERVICE_CONTROL_STOP代码。
- 仅当服务在与挂起的启动、停止、暂停或继续操作相关的任务上取得进展时,才使用检查点和等待提示值调用此函数。 否则,SCM 无法检测服务是否挂起。
- 如果 ServiceMain 失败,请使用相应的退出代码输入停止状态。
- 如果状态为SERVICE_STOPPED,请执行所有必要的清理,并仅调用 一次 SetServiceStatus 。 此函数对 SCM 进行 LRPC 调用。 第一次调用处于SERVICE_STOPPED状态的函数将关闭 RPC 上下文句柄,任何后续调用都可能导致进程崩溃。
- 使用 SERVICE_STOPPED 调用 SetServiceStatus 后,请勿尝试执行任何其他工作,因为服务进程可以随时终止。
示例
有关示例,请参阅 编写 ServiceMain 函数。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows XP [仅限桌面应用] |
最低受支持的服务器 | Windows Server 2003 [仅限桌面应用] |
目标平台 | Windows |
标头 | winsvc.h (包括 Windows.h) |
Library | Advapi32.lib |
DLL | Advapi32.dll |