如何从java应用程序创建一个windows服务

我刚刚继承了一个java应用程序,需要在XP和vista上作为服务安装。我已经8年没有使用任何形式的windows了,我从来没有创建过服务,更不用说从java应用程序(我已经为应用程序准备了一个jar和一个依赖jar - log4j)。使其作为服务运行所必需的魔力是什么?我已经得到了源代码,所以代码修改(尽管最好避免)是可能的。

330782 次浏览

我已经有一些运气Java服务包装器

我曾经成功地使用过JavaService。它已经有几年没有更新了,但当我使用它的时候,它非常坚固。

我不喜欢Java服务包装器的授权。我使用ActiveState Perl编写了一个完成这项工作的服务。

我想过用c#写一个服务,但是我的时间太紧了。

我总是只使用sc.exe(见http://support.microsoft.com/kb/251192)。它应该安装在从SP1开始的XP上,如果它不符合你的Vista风格,你可以通过Vista资源包下载加载它。

我没有使用Java做过太复杂的事情,但是使用完全限定的命令行参数(x:\ Java .exe ....)或使用Ant创建一个脚本来包含依赖项和设置参数对我来说都很好。

我认为Java服务包装器工作得很好。注意有三种方式来集成你的应用程序。如果您不想更改代码,那么听起来选项1最适合您。配置文件可能有点疯狂,但只要记住(对于选项1)您正在启动并将为其指定参数的程序是它们的辅助程序,然后它将启动您的程序。他们有一个配置文件示例

另一个不错的选项是FireDaemon。它被一些大公司使用,比如NASA、IBM等;他们的网站上有完整的列表。

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

再见!

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

(完全披露:我参与了这个项目)。

JavaService是LGPL。这是非常容易和稳定的。强烈推荐。

Apache Commons Daemon是一个不错的选择。它有Procrun用于windows服务,Jsvc用于unix守护进程。它使用限制较少的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()"会导致错误。如果您不能修改这些调用,请考虑创建一个bootstrapper类,它可以根据您的需要修改这些调用。

还有一个答案是另一个Java服务包装器,这似乎是Java服务包装器的一个很好的选择,因为有更好的许可。它的目的还在于便于从JSW迁移到YAJSW。当然,对于我这个刚刚接触windows服务器并试图让Java应用程序作为服务运行的人来说,它非常容易使用。

我发现了一些其他的,但最终没有使用:

  • Java服务启动器我没有使用这个,因为它看起来比YAJSW更复杂。我觉得这不是包装。
  • JSmooth创建Window的服务不是它的主要目标,但是可以做到. 0创建windows的服务不是它的主要目标。我没用这个,因为从2007年开始就没有活动了。
以下是不同解决方案的比较: http://yajsw.sourceforge.net/#mozTocId284533 < / p >

个人喜欢launch4j

使用“winsw”,它是为Glassfish v3编写的,但通常与Java程序一起工作得很好。

要求安装。net运行时。

使用Apache Commons Daemon你现在可以有一个自定义的可执行名称和图标!你也可以得到一个自定义的Windows托盘显示器与你自己的名字和图标!

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

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

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

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

    > 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
    

一个简单的方法是NSSM包装包装器(看我的博客)。

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

< >强Windows 7 C:\users\All Users\Start Menu\Programs\Startup(Admin)或User home directory(%userProfile%)

Windows 10: 在“Run shell:startup

. sh”中输入“> . sh”

在它的属性-> shortcut -> target -> java.exe -jar D:\..\runJar.jar

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


拥有管理员权限

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

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

注意:这将在windows登录启动时运行(在登录之前,基于服务'Startup Type')

创建windows服务的详细说明

如果你使用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. Include the plugin into your build.gradle file.

    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. Configure the plugin.

    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. Run createWindowsService gradle task to create a windows service distribution.

That's all you need to do to create a simple windows service. The plugin will automatically download Apache Commons Daemon Procrun binaries, extract this binaries to the service distribution directory and create batch files for installation/uninstallation of the service.

In ${project.buildDir}/windows-service directory you will find service executables, batch scripts for installation/uninstallation of the service and all runtime libraries. To install the service run <project-name>-install.bat and if you want to uninstall the service run <project-name>-uninstall.bat. To start and stop the service use <project-name>w.exe executable.

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

For more information, please read about the plugin and Apache Commons Daemon Procrun.

使用Java 8,我们可以在没有任何外部工具的情况下处理这种情况。java 8附带的javapackager工具提供了一个选项来创建自包含的应用程序包:

< p >原生类型 生成自包含的应用程序包(如果可能的话)。使用-B选项为正在使用的绑定器提供参数。如果指定了type,则只创建该类型的bundle。如果不指定类型,则使用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.

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

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

请看这个例子,它概述了实现Windows服务所需的工作。所有Windows服务EXE必须为主入口点ServiceMain服务控制处理器提供回调,并在Advapi.DLL中使用API调用StartServiceCtrlDispatcherWRegisterServiceCtrlHandlerExWSetServiceStatus

在具有外部内存结构的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"