1

TL;DR:我有一个用 Java 编写的 Windows 服务,经过 jarred 处理,并与 Procrun 一起安装。我从W32Service.startService(). 该服务何时告诉 Windows 它已启动?


我正在使用用 Java 编写的 Windows 服务。我一直在使用Procrun来安装它们,并使用 JNA 来使用它们(特别是com.sun.jna.platform.win32.W32Service)。

我想了解对象方法的确切行为(这是我的 Y 的 X:了解的确切行为)。W32ServicewaitForNonPendingState()startService()

waitForNonPendingState()实际上非常简单:它会轮询服务的状态,直到它处于非挂起状态或发生超时。不过,服务如何转换到非挂起状态并不是那么简单。

微软的服务状态转换页面说:

服务的初始状态是 SERVICE_STOPPED。当 SCM 启动服务时,它将服务状态设置为 SERVICE_START_PENDING 并调用服务的ServiceMain函数。然后,该服务使用Service ServiceMain Function中描述的技术之一完成其初始化。服务完成初始化并准备开始接收控制请求后,服务调用SetServiceStatus报告 SERVICE_RUNNING...

但这并没有真正说明服务如何做到这一点。ServiceMain备注也只是说“服务控制管理器 (SCM) 等待服务报告 SERVICE_RUNNING 状态。 ”;这几乎和我能找到的一样具体。

这让我想到了我的问题:java Windows 服务如何“知道”它已完成初始化?

换句话说,如果我有一个使用main()方法安装的服务:

public class SampleService {

    public static void main(String[] args) {
        if ("start".equals(args[0]))
            new SampleService();
    }

    public SampleService() {
        // do a whole bunch of stuff
    }
}

我打电话给:

W32Service service = serviceManager.openService("SampleService", 
                                                Winsvc.SC_MANAGER_ALL_ACCESS);
service.startService();

我在什么时候SampleService告诉 Windows 它已经初始化?通过实验,我可以看到,如果在构建过程中出现运行时异常,则服务的状态永远不会是SERVICE_RUNNING,因此该进程中有一些东西设置了该状态。但是我的一些构造函数等待队列或进入自旋循环,他们确实设置了 SERVICE_RUNNING 状态,所以我不知道这个状态是在哪里设置的。W32Service 的文档在这方面并没有什么用处。

4

1 回答 1

0

您的服务并没有真正公开为常规服务,它依赖于 Procrun,只要 JVM 作为进程的一部分生成或单独将服务状态设置为运行。在prunsrv.c其中有 procrun 的服务容器代码,您可以检查如何serviceStart()调用以及成功时会发生什么。

于 2018-07-13T07:17:38.383 回答