服务状态转换

服务负责将状态更改报告给服务控制管理器 (SCM) 。 服务控制程序和系统只能从 SCM 中找出服务的状态,因此服务必须正确报告其状态。 服务通过使用指向完全初始化的SERVICE_STATUS结构的指针调用 SetServiceStatus 函数来报告其状态。 结构的 dwCurrentState 成员包含要报告的服务状态。

服务的初始状态为SERVICE_STOPPED。 当 SCM 启动服务时,它将服务状态设置为 SERVICE_START_PENDING 并调用服务的 ServiceMain 函数。 然后,该服务使用 Service ServiceMain 函数中所述的技术之一完成初始化。 服务完成初始化并准备好开始接收控制请求后,该服务将调用 SetServiceStatus 来报告SERVICE_RUNNING并指定服务准备接受的控制请求。 从SERVICE_START_PENDING转换到SERVICE_RUNNING向 SCM 和服务监视工具指示服务已成功启动。 如果服务报告SERVICE_RUNNING以外的状态,SCM 或服务监视工具可能会将服务标记为无法启动。

SCM 仅将指定的控制请求发送到服务 (,SERVICE_CONTROL_INTERROGATE请求始终) 发送。 有关服务可以接受的控制请求的列表,请参阅SERVICE_STATUS结构的 dwControlsAccepted 成员。 有关注册以接收设备事件的信息,请参阅 RegisterDeviceNotification 函数。

服务状态通常会因处理控制请求而更改。 导致服务状态更改的控制请求包括SERVICE_CONTROL_STOP、SERVICE_CONTROL_PAUSE和SERVICE_CONTROL_CONTINUE。 如果服务必须执行冗长的处理才能处理其中任何请求,则它应创建一个辅助线程来执行冗长的处理,并将相应的挂起状态报告给 SCM。 (为了在 Windows Vista 和更高版本的 Windows 上获得最佳性能,服务应出于此目的使用 线程池 中的工作线程。) 完成冗长的处理后,服务应报告已完成的状态转换。 有关处理控制请求的详细信息,请参阅 服务控制处理程序函数

只有某些服务状态转换有效。 下图显示了有效的转换。

有效的服务状态转换

向 SCM 报告的服务状态决定了 SCM 如何与服务交互。 例如,如果服务报告SERVICE_STOP_PENDING,则 SCM 不会将进一步的控制请求传输到服务,因为此状态指示服务正在关闭。 服务报告的下一个状态应SERVICE_STOPPED,因为这是SERVICE_STOP_PENDING后唯一有效的状态。 但是,如果服务报告无效的转换,则 SCM 不会使调用失败。

下图更详细地显示了服务状态转换,包括服务控制程序 (服务客户端) 发起的控制请求,以及服务为报告 SCM 状态更改而调用 的 SetServiceStatus 。 如前所述,SCM 仅发送服务指定它将接受的控制请求,因此服务可能不会接收图中显示的所有请求。

服务状态转换的详细信息

ControlService

ControlServiceEx

SetServiceStatus