如何将守护程序实现设置为 windows 服务

Howto setup a Daemon implementation as windows service

我没有找到任何关于如何将实现 org.apache.commons.daemon.Daemon 接口的 class 注册为 Windows 服务的真正好的示例(实际上我没有找到一个示例) .

我必须使用 procrun 注册这个实现吗?但是似乎没有实现接口的意义,因为 procrun 可以将任何程序注册为 windows 服务。

此外,procrun 页面上似乎有一个文档错误 (http://commons.apache.org/proper/commons-daemon/procrun.html):

--StartMethod 参数的描述指出:

Note: in jvm mode, the start method should not return until the stop method has been called.

但在 "Using Procrun in jvm mode" 部分的页面下方:

Note that the method handling service start should create and start a separate thread to carry out the processing, and then return. The start and stop methods are called from different threads.

我是不是读错了,还是有点矛盾??静态 start(String[] args) 方法的正确行为是什么?

此致

备案:

Do I have to register this implementation using procrun? But than there doesn't seem to be a point in implementing the interface as procrun can register any program as windows service.

是的,需要使用 prunsrv 在 Windows 中注册该服务。例如使用以下调用:

prunsrv.exe //IS//MyTestService ^
    --DisplayName="My Test Service" --Description="Doesn't really do anything" ^
    --Install=@@PATH_TO_PRUNSRV@@\prunsrv.exe ^
    --Startup=manual ^
    --Jvm=auto ^
    --Classpath="@@PUT_FULL_CLASSPATH_HERE@@" ^
    --StartMode=jvm ^
    --StartClass==com.Whosebug.questions.31556478.ServiceLauncher ^
    --StartParams="@@PUT_ANY_START_ARGUMENTS_HERE@@" ^
    --StartMethod=start ^
    --StopMode=jvm ^
    --StopClass=com.Whosebug.questions.31556478.ServiceLauncher ^
    --StopMethod=stop

在此之后可以通过

启动服务
prunsrv //ES//MyTestSevice


And what would be the correct behavior of a static start(String[] args) method?

测试这两种变体,只有实现有效,它停留在启动方法中,没有产生额外的线程。这是一个可以使用上述 prunsrv 调用注册的启动器实现,看起来像这样(没有任何保证):

package com.Whosebug.questions.31556478;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ServiceLauncher
{
  private static final Logger LOGGER = LoggerFactory.getLogger(ServiceLauncher.class);

  private static SomeServer mServer;

  public static void start(final String[] args)
  {
    LOGGER.debug("Start called: {}", Arrays.toString(args));

    try
    {
      mServer = new SomeServer(args);
      mServer.start();
    }
    catch (final Exception e)
    {
      LOGGER.error("Terminating due to Exception: ", e);
    }
  }

  public static void stop(final String[] args) throws Exception
  {
    LOGGER.debug("Stop called: {}", Arrays.toString(args));

    synchronized (ServiceLauncher.class)
    {
      if (mServer != null)
      {
        mServer.stop();
      }
    }
  }
}