如何从 java 应用创建 Windows 服务

How to create a windows service from java app

提问人: 提问时间:9/16/2008 最后编辑:2 revs, 2 users 100%ideasculptor 更新时间:6/17/2022 访问量:342244

问:

我刚刚继承了一个 java 应用程序,需要将其作为服务安装在 XP 和 vista 上。自从我以任何形式使用窗口以来已经有大约 8 年了,我从来没有创建过服务,更不用说从 java 应用程序之类的东西了(我有一个用于该应用程序的 jar 和一个依赖 jar - log4j)。让它作为服务运行所需的魔力是什么?我有源代码,所以代码修改,虽然最好避免,但也是可能的。

java windows 服务

评论

0赞 bhdrkn 5/13/2014
另一个建议 stackoverflow.com/a/9262081/381897
1赞 Broken_Window 8/18/2015
只是为了完整起见:此处 serverfault.com/a/259195 它说应用需要响应服务控制管理器回调。阅读本教程,它使用 Procrun ticklingmind.blogspot.com/2010/03/...
0赞 Ravi Parekh 2/13/2017
其他答案 stackoverflow.com/questions/5953525/...

答:

74赞 sblundy 9/16/2008 #1

我在 Java Service Wrapper 上有一些运气

评论

13赞 Brian Matthews 9/16/2008
Java Service Wrapper 看起来非常有用。但是我看了一下功能列表。您只需要知道社区版未获得在服务器上使用的许可。
0赞 sblundy 9/16/2008
这可能是一个问题。几年前我用过它。猜猜他们决定收费。
0赞 Todd 9/16/2008
这个包装器被许多开源项目使用,包括 Jakarta Apache 上的几个项目,例如 ActiveMQ。
7赞 Vladimir 12/31/2009
wrapper.tanukisoftware.org/doc/english/licenseCommunity.html闭源使用 GPL 并不限制私有软件被开发用于内部使用,这取决于 GPL 下的软件,只要该软件在未向所有用户提供整个应用程序的完整源代码的情况下永远不会被分发。虽然我们鼓励企业和政府用户使用服务器或开发许可协议,但只要应用程序供内部使用或始终与其完整 src 一起分发,社区许可协议是可以接受的。
1赞 gerrytan 7/4/2014
@Vladimir tanuki 包装器不再为 64 位 arch 开源
2赞 Jason 9/16/2008 #2

我以前使用过 JavaService,并取得了很好的成功。它已经有几年没有更新了,但当我使用它时,它非常坚如磐石。

评论

0赞 lww 6/7/2020
GForge 已停产
0赞 Gary Sheppard 12/9/2020
工作链接:multiplan.co.uk/software/javaservice(文档)download.forge.ow2.org/javaservice(源代码和二进制文件) 我继承了一个使用 JavaService 的项目。它满足了我们的需求,即使它现在有点古老。
2赞 Hugh Buchanan 9/16/2008 #3

我不喜欢 Java Service Wrapper 的许可。我用 ActiveState Perl 编写了一个完成这项工作的服务。

我考虑过用 C# 编写服务,但我的时间限制太紧了。

评论

0赞 peaceUser 10/15/2016
你能提供你用“perl”完成的示例hack吗..!
2赞 Kevin 9/16/2008 #4

我总是只使用 sc.exe(见 http://support.microsoft.com/kb/251192)。它应该从 SP1 安装在 XP 上,如果它不在您的 Vista 风格中,您可以下载并使用 Vista 资源工具包加载它。

我没有用 Java 做任何太复杂的事情,但是使用完全限定的命令行参数 (x:\java.exe ....) 或使用 Ant 创建脚本以包含 depencies 和设置参数对我来说效果很好。

评论

1赞 atomicules 9/2/2010
这允许你以服务的形式启动某些东西,但在我的理解中,它随后将被分离,即你不能通过服务停止它或自动重启,等等。不过,我可能完全错了——才刚刚开始研究这个问题。
6赞 Ed Thomas 9/16/2008 #5

我认为 Java Service Wrapper 运行良好。请注意,有三种方法可以集成应用程序。听起来选项 1 最适合您,因为您不想更改代码。配置文件可能会变得有点疯狂,但请记住(对于选项 1)您正在启动的程序以及您将为其指定参数的程序是它们的帮助程序,然后它将启动您的程序。他们为此提供了一个示例配置文件

1赞 Andrew Swan 9/16/2008 #6

另一个不错的选择是 FireDaemon。它被 NASA、IBM 等一些大商店使用;有关完整列表,请参阅他们的网站。

1赞 ramfree17 9/23/2008 #7

我目前需要它来运行基于 Eclipse 的应用程序,但我需要先设置一些该应用程序的本地变量。sc.exe 只允许可执行文件,而不允许脚本,所以我转向 autoexnt.exe,它是 Windows 2003 资源工具包的一部分。它将服务限制为单个批处理文件,但我只需要一个批处理脚本即可转换为服务。

再见!

29赞 Peter Smith #8

另一个选项是 WinRun4J。这是一个可配置的 java 启动器,可兼作 Windows 服务主机(32 位和 64 位版本)。它是开源的,使用没有限制。

(完全披露:我从事这个项目)。

评论

3赞 fernacolo 5/16/2011
谢谢你。我尝试过 YAJWS,首先它用 19mb 的下载吓到我,在我按照说明操作后,它显示“解析命令行时出错”。我看过 PROCRUN,它对于快速设置来说太麻烦了。INSTSRV / SRVANY需要更改注册表!Launch4J 将 JAR 打包在 EXE 中,因此它使部署复杂化。WinRun4J 是一个完美的选择。唯一的缺点是它需要一个特殊的类来作为服务工作(而不是简单地调用标准的主类)。但总的来说,它是 99% 完美的。
3赞 Peter Smith 9/19/2011
仅供参考,最新版本有一个标准主类的包装器。
0赞 Krunal 1/8/2015
嗨,你能举出任何例子来解释如何使用它吗?我想在系统启动时使用它来启动HelioSearch实例作为后台Windows服务。
4赞 NT_ #9

JavaService 是 LGPL。它非常简单和稳定。强烈推荐。

107赞 4 revs, 4 users 62%mcdon #10

Apache Commons Daemon 是一个不错的选择。它有用于 Windows 服务的 Procrun,以及用于 unix 守护进程的 Jsvc。它使用限制较少的 Apache 许可证,Apache Tomcat 将其用作自身的一部分,以便在 Windows 和 Linux 上运行!要让它工作有点棘手,但有一篇详尽的文章提供了工作示例。

除此之外,您可以查看Apache Tomcat中的bin\service.bat,以了解如何设置服务。在 Tomcat 中,它们重命名了 Procrun 二进制文件(prunsrv.exe -> tomcat6.exe、prunmgr.exe -> tomcat6w.exe)。

我在使用 Procrun 时遇到了一些困难,您的启动和停止方法必须接受参数 (String[] argv)。例如,“start(String[] argv)”和“stop(String[] argv)”可以工作,但“start()”和“stop()”会导致错误。如果您无法修改这些调用,请考虑创建一个引导程序类,该类可以调整这些调用以满足您的需求。

评论

0赞 djangofan 11/9/2011
使用反思,你可能会绕过你在上一段中提到的问题。此外,apache commons 守护程序是我所知道的唯一一个具有预构建的 64 位二进制文件供免费使用的包装器。
1赞 Sydney 3/14/2012
您需要在每个 JVM 选项之间有一个回车符。例如,如果您在同一行上有 -Dopt1=a -Dopt2=b,它可能不起作用。要修复它,您需要编写 .我从蚂蚁脚本运行命令,因此挣扎了好几天。希望它有所帮助。--JvmOptions=-Dopt=a#-Dopt2=b
0赞 11101101b 5/24/2012
你说的那篇文章已经不存在了......你还有办法去吗?我无法让 Apache Commons Daemon 做我需要的事情。
4赞 Lucas 6/28/2012
@11101101b,Apache 似乎已经将文章的胆量附加到自己的 wiki 页面上......
0赞 Shakthi 12/29/2014
@community wiki 中,我在 64 位 Windows 机器上使用 Apache Commons Daemon,它成功添加了该服务。当我对 32 位 Windows 7 机器使用相同的进程时,它无法添加服务。
18赞 atomicules #11

另一个答案是 Yet Another Java Service Wrapper,这似乎是 Java Service Wrapper 的一个很好的替代品,因为它具有更好的许可。它还旨在轻松地从 JSW 移动到 YAJSW。当然,对于我来说,我是 Windows 服务器的新手,并且试图将 Java 应用程序作为服务运行,它非常易于使用。

我找到了其他一些,但最终没有使用:

  • Java 服务启动器我没有使用它,因为它看起来比 YAJSW 更复杂。我不认为这是一个包装器。
  • JSmooth创建 Window 的服务不是它的主要目标,但可以做到。我没有使用它,因为自 2007 年以来就没有活动。

评论

0赞 Green Day 11/8/2013
+1 来自我,因为这是我“开箱即用”的最快解决方案,不需要修改 Java 应用程序,这绝对是一个加分项。
0赞 Green 6/18/2014
我发现了这个非常引人注目的比较图表,它将 YAJSW 与其他一些常见的服务包装器进行了比较。yajsw.sourceforge.net/#mozTocId284533
3赞 pushNpop #12

不同解决方案的比较可以在以下位置找到:http://yajsw.sourceforge.net/#mozTocId284533

个人喜欢launch4j

5赞 3 revs, 3 users 44%Thorbjørn Ravn Andersen #13

使用“winsw”,它是为 Glassfish v3 编写的,但通常适用于 Java 程序。

需要安装 .NET 运行时。

评论

1赞 FrVaBe 4/18/2013
同时,当前版本(由著名的 Kohsuke Kawaguchi 维护)位于此处
0赞 Thorbjørn Ravn Andersen 4/18/2013
似乎他在 1.9 版之后将其移到了 github(很可能是当他从 Oracle 转到 Cloudbees 时)。
71赞 3 revs, 3 users 91%11101101b #14

使用 Apache Commons Daemon,您现在可以拥有自定义的可执行文件名称和图标!您还可以获得带有自己名称和图标的自定义 Windows 托盘显示器!

我现在使用我自己的名称和图标(prunsrv.exe)运行我的服务,系统托盘监视器(prunmgr.exe)也有我自己的自定义名称和图标!

  1. 下载Apache Commons Daemon二进制文件(您将需要prunsrv.exe和prunmgr.exe)。

  2. 将它们分别重命名为 和。MyServiceName.exeMyServiceNamew.exe

  3. 下载 WinRun4J 并使用它附带的程序修改 Apache 可执行文件以嵌入您自己的自定义图标,如下所示:RCEDIT.exe

    > RCEDIT.exe /I MyServiceName.exe customIcon.ico
    > RCEDIT.exe /I MyServiceNamew.exe customTrayIcon.ico
    
  4. 现在像这样安装 Windows 服务(有关更多详细信息和选项,请参阅文档):

    > MyServiceName.exe //IS//MyServiceName \
      --Install="C:\path-to\MyServiceName.exe" \
      --Jvm=auto --Startup=auto --StartMode=jvm \
      --Classpath="C:\path-to\MyJarWithClassWithMainMethod.jar" \
      --StartClass=com.mydomain.MyClassWithMainMethod
    
  5. 现在你有了一个 Jar 的 Windows 服务,它将使用你自己的图标和名称运行!您还可以启动监控文件,它将在系统托盘中运行,并带有您自己的图标和名称。

    > MyServiceNamew.exe //MS//MyServiceName
    

评论

1赞 outofBounds 6/12/2012
我按照您的操作方法做了所有操作,但它不会更改系统托盘图标.知道为什么吗?
0赞 11101101b 12/3/2012
对不起@outofBounds,直到刚才我才看到你的评论。RCEDIT.exe 程序用于修改服务可执行文件的图标。确保您有一个有效的 .ico 文件,其中每个大小都已正确定义。您可以在此处了解如何创建适当的 .ico 文件: stackoverflow.com/questions/4354617/...
2赞 11101101b 10/3/2013
如您所知,服务名称中不能有空格。
1赞 11101101b 12/31/2014
是的,@Shakthi它在 32 位和 64 位 Windows XP、7、8、8.1、Server 2003、2008 和 2012 上运行良好。
1赞 11101101b 1/21/2019
是的,@Syamsoul Azrein,它在 10 和任何服务器版本上运行良好。
32赞 2 revs, 2 users 89%Giordano Maestro #15

一个简单的方法是 NSSM Wrapper Wrapper(请参阅我的博客文章)。

评论

7赞 cynepnaxa 3/20/2014
NSSM摇滚!我甚至可以轻松地从我的 java 程序中制作包装器。简单,轻巧,有效 - 100kb的幸福!谢谢!
1赞 Krunal 1/8/2015
任何示例,如何在系统启动时使用 NSSM Wrapper 启动 java 应用程序(我正在使用 HelioSearch)实例作为 Windows 服务?
2赞 Jeffrey Knight 3/20/2016
在Apache Commons Daemon、wrapper.tanukisoftware.org 和yajsw上相比,NSSM是迄今为止将简单的Java应用程序转换为Windows服务的最快和最简单的选择
1赞 VenVig 1/24/2019
有一个带有java -jar myapp.jar的.cmd文件,它运行我的java应用程序。几乎在 3 分钟内将其安装为一项服务。如此轻而易举..我唯一的抱怨是这个名字。你能想出一个使用“S***”这个词的更好的名字吗?
1赞 VenVig 9/26/2020
@NikhilSinghBhadoriya抱歉,直到现在才注意到这个问题。但是,如果您碰巧仍然需要它,我所做的只是在 Windows 批处理文件中使用 java -jar 命令,并指示 NSSM 将该批处理文件作为服务运行。
2赞 2 revsRavi Parekh #16

这很简单,因为你必须输入快捷方式

Windows 7 (Admin) 或C:\users\All Users\Start Menu\Programs\StartupUser home directory(%userProfile%)

视窗10:运行中shell:startup

在它的属性中 -> 快捷方式 -> 目标 - >java.exe -jar D:\..\runJar.jar

注意:这只会在您登录后运行


具有管理员权限

sc create serviceName binpath= "java.exe -jar D:\..\runJar.jar"将创建 Windows 服务

如果您获得超时使用,但即使这样,您也将获得超时,但在后台 java.exe 将启动。签入任务管理器cmd /c D:\JAVA7~1\jdk1.7.0_51\bin\java.exe -jar d:\jenkins\jenkins.war

注意:这将在 Windows 登录启动时运行(登录前,基于服务“启动类型”)

创建 Windows 服务的详细说明

评论

0赞 ostergaard 6/24/2021
这个答案的第一部分完全没有回答这个问题,第二部分是完全错误的。SC 不能用于从常规 Java.exe 创建服务。
10赞 4 revs, 2 users 99%Alexey Lisyutenko #17

如果您使用 Gradle 构建工具,您可以尝试我的 windows-service-plugin,它有助于使用 Apache Commons Daemon Procrun

要使用插件创建 java windows 服务应用程序,您需要完成几个简单的步骤。

  1. 使用适当的方法创建主服务类。

    public class MyService {
    
        public static void main(String[] args) {
            String command = "start";
            if (args.length > 0) {
                command = args[0];
            }
            if ("start".equals(command)) {
                // process service start function
            } else {
                // process service stop function
            }
        }
    
    }
    
  2. 将插件包含在您的文件中。build.gradle

    buildscript {
      repositories {
        maven {
          url "https://plugins.gradle.org/m2/"
        }
      }
      dependencies {
        classpath "gradle.plugin.com.github.alexeylisyutenko:windows-service-plugin:1.1.0"
      }
    }
    
    apply plugin: "com.github.alexeylisyutenko.windows-service-plugin"
    

    Gradle 2.1 中引入的新的孵化插件机制的脚本片段相同:

    plugins {
      id "com.github.alexeylisyutenko.windows-service-plugin" version "1.1.0"
    }
    
  3. 配置插件。

    windowsService {
      architecture = 'amd64'
      displayName = 'TestService'
      description = 'Service generated with using gradle plugin'   
      startClass = 'MyService'
      startMethod = 'main'
      startParams = 'start'
      stopClass = 'MyService'
      stopMethod = 'main'
      stopParams = 'stop'
      startup = 'auto'
    }
    
  4. 运行 createWindowsService gradle 任务以创建 Windows 服务分发。

这就是创建简单的 Windows 服务所需要执行的全部操作。该插件将自动下载 Apache Commons Daemon Procrun 二进制文件,将此二进制文件提取到服务分发目录,并创建用于安装/卸载服务的批处理文件。

在目录中,您将找到服务可执行文件、用于安装/卸载服务的批处理脚本以及所有运行时库。 要安装服务,请运行,如果要卸载服务,请运行 。 若要启动和停止服务,请使用可执行文件。${project.buildDir}/windows-service<project-name>-install.bat<project-name>-uninstall.bat<project-name>w.exe

请注意,方法处理服务 start 应创建并启动一个单独的线程来执行处理,然后返回。当您启动和停止服务时,将从不同的线程调用 main 方法。

有关更多信息,请阅读有关插件和 Apache Commons Daemon Procrun 的信息。

评论

1赞 TaylanKammer 12/5/2018
被低估的答案!
0赞 E-Riz 6/27/2023
它是否可以参与 Gradle,以便生成的文件可以打包并推送到 atifact 存储库(如 JAR 和 WAR)?packagepublish
4赞 Steephen #18

在 Java 8 中,我们可以在没有任何外部工具的情况下处理这种情况。Java 8 附带的 JavaPackager 工具提供了创建独立应用程序包的选项:

-原生类型 生成独立的应用程序包(如果可能)。使用 -B 选项为正在使用的捆绑器提供参数。如果指定了 type,则仅创建此类型的捆绑包。如果未指定类型,则使用 all。

以下值对 type 有效:

-native type
Generate self-contained application bundles (if possible). Use the -B option to provide arguments to the bundlers being used. If type is specified, then only a bundle of this type is created. If no type is specified, all is used.

The following values are valid for type:

all: Runs all of the installers for the platform on which it is running, and creates a disk image for the application. This value is used if type is not specified.
installer: Runs all of the installers for the platform on which it is running.
image: Creates a disk image for the application. On OS X, the image is the .app file. On Linux, the image is the directory that gets installed.
dmg: Generates a DMG file for OS X.
pkg: Generates a .pkg package for OS X.
mac.appStore: Generates a package for the Mac App Store.
rpm: Generates an RPM package for Linux.
deb: Generates a Debian package for Linux.

如果是 Windows,请参阅以下文档,我们可以根据需要创建 msi 或 exe。

exe: Generates a Windows .exe package.
msi: Generates a Windows Installer package.

评论

9赞 tobias_ 11/23/2017
这个答案没有解决这个问题。javapackager 不能直接用于创建 Windows 服务,而是创建一个独立的可执行文件,例如包含 jre 和其他资源。
1赞 Ram #19

在过去的几年里,我一直在使用 jar2exe 在 Windows 上将我们的 Java 应用程序作为服务运行。它提供了一个选项来创建一个可以作为 Windows 服务安装的 exe 文件。

1赞 2 revsDuncG #20

通过将外部内存和链接器 API(从 JDK16 向上预览)与 OpenJDK jextract 项目相结合,可以在 100% Java 代码中实现 Windows 服务,以处理 Windows 服务回调,然后使用 jpackage 生成 Windows EXE,然后可以注册为 Windows 服务。

请参阅此示例,其中概述了实现 Windows 服务所需的工作。所有 Windows 服务 EXE 都必须为主入口点 ServiceMain 和服务控制处理程序提供回调,并使用 API 调用 StartServiceCtrlDispatcherWRegisterServiceCtrlHandlerExWSetServiceStatusAdvapi.DLL

Java 中具有外部内存结构的上述回调的流程为:

main()
    Must register ServiceMain using StartServiceCtrlDispatcherW
    Above call blocks until ServiceMain exits
        
void ServiceMain(int dwNumServicesArgs, MemoryAddress lpServiceArgVectors)
    Must register SvcCtrlHandler using RegisterServiceCtrlHandlerExW
    Use SetServiceStatus(SERVICE_START_PENDING)
    Initialise app
    Use SetServiceStatus(SERVICE_RUNNING)
    wait for app shutdown notification
    Use SetServiceStatus(SERVICE_STOPPED)

int SvcCtrlHandler(int dwControl, int dwEventType, MemoryAddress lpEventData, MemoryAddress lpContext)
    Must respond to service control events and report back using SetServiceStatus
    On receiving SERVICE_CONTROL_STOP reports SetServiceStatus(SERVICE_STOP_PENDING)
        then set app shutdown notification

完成 Java 应用程序后,jpackage 可以创建运行时 + EXE,然后可以安装并注册为 Windows 服务。以管理员身份运行(= 后面的空格很重要):

 sc create YourJavaServiceName type= own binpath= "c:\Program Files\Your Release Dir\yourjavaservice.exe"