为Windows/Linux桌面打包Java应用程序

40

我正在使用Eclipse SWT库编写一个Java桌面应用程序,用于GUI渲染。我认为SWT有助于Java克服在桌面上被接受的最大障碍:即为Java应用程序提供一个一致、反应迅速、外观与桌面上任何其他应用程序相同的界面。但是,我认为打包应用程序仍然是个问题。

OS X本地提供了一种简单的机制,可以将Java应用程序封装成本机应用程序捆绑包,但为Windows/Linux生成一个不需要用户运行丑陋的批处理文件或单击.jar文件仍然很麻烦。可能在Linux上这不是太大的问题,因为用户可能会更懂技术,但在Windows上,我希望为用户提供一个常规的.exe文件来运行。

有没有人有使用Java中的.exe生成工具的经验?我已经尝试了JSmooth,但遇到了各种问题。在我启动Visual Studio并自己开发之前,有没有更好的解决方案?

编辑:我应该提到,我无法花费大量资金购买商业解决方案。


1
请列出您在使用JSmooth时遇到的问题。 - Thorbjørn Ravn Andersen
18个回答

32

参考pauxu的回答,我正在使用launch4j和NSIS工具在我的项目中。以下是我在Windows上的操作步骤。另外,我也在为 Mac 创建 .app 和 .dmg 文件,但还没有想出如何在 Linux 上操作。

项目中的 launch4j 和 NSIS 拷贝

在我的项目中,我有一个 "vendor" 目录,其中包含 "launch4j" 和 "nsis" 目录。每个目录下都有各自的应用程序安装包。我发现将这些应用程序的副本存储在项目本地会更方便一些,不需要让其他人安装这两个产品并设置某种环境变量来指向它们。

脚本文件

在我的项目中,我还有一个名为 "scripts" 的目录,用于存放各种配置/脚本文件。首先是 launch4j.xml 文件:

<launch4jConfig>
  <dontWrapJar>true</dontWrapJar>
  <headerType>gui</headerType>
  <jar>rpgam.jar</jar>
  <outfile>rpgam.exe</outfile>
  <errTitle></errTitle>
  <cmdLine></cmdLine>
  <chdir>.</chdir>
  <priority>normal</priority>
  <downloadUrl>http://www.rpgaudiomixer.com/</downloadUrl>
  <supportUrl></supportUrl>
  <customProcName>false</customProcName>
  <stayAlive>false</stayAlive>
  <manifest></manifest>
  <icon></icon>
  <jre>
    <path></path>
    <minVersion>1.5.0</minVersion>
    <maxVersion></maxVersion>
    <jdkPreference>preferJre</jdkPreference>
  </jre>
  <splash>
    <file>..\images\splash.bmp</file>
    <waitForWindow>true</waitForWindow>
    <timeout>60</timeout>
    <timeoutErr>true</timeoutErr>
  </splash>
</launch4jConfig>

还有一个名为rpgam-setup.nsis的NSIS脚本。它可以使用VERSION参数来命名文件。

; The name of the installer
Name "RPG Audio Mixer"

!ifndef VERSION
    !define VERSION A.B.C
!endif

; The file to write
outfile "..\dist\installers\windows\rpgam-${VERSION}.exe"

; The default installation directory
InstallDir "$PROGRAMFILES\RPG Audio Mixer"

; Registry key to check for directory (so if you install again, it will 
; overwrite the old one automatically)
InstallDirRegKey HKLM "Software\RPG_Audio_Mixer" "Install_Dir"

# create a default section.
section "RPG Audio Mixer"

    SectionIn RO

    ; Set output path to the installation directory.
    SetOutPath $INSTDIR
    File /r "..\dist\layout\windows\"

    ; Write the installation path into the registry
    WriteRegStr HKLM SOFTWARE\RPG_Audio_Mixer "Install_Dir" "$INSTDIR"

    ; Write the uninstall keys for Windows
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RPGAudioMixer" "DisplayName" "RPG Audio Mixer"
    WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RPGAudioMixer" "UninstallString" '"$INSTDIR\uninstall.exe"'
    WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RPGAudioMixer" "NoModify" 1
    WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RPGAudioMixer" "NoRepair" 1
    WriteUninstaller "uninstall.exe"

    ; read the value from the registry into the $0 register
    ;readRegStr $0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" CurrentVersion

    ; print the results in a popup message box
    ;messageBox MB_OK "version: $0"

sectionEnd

Section "Start Menu Shortcuts"
  CreateDirectory "$SMPROGRAMS\RPG Audio Mixer"
  CreateShortCut "$SMPROGRAMS\RPG Audio Mixer\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
  CreateShortCut "$SMPROGRAMS\RPG AUdio Mixer\RPG Audio Mixer.lnk" "$INSTDIR\rpgam.exe" "" "$INSTDIR\rpgam.exe" 0
SectionEnd

Section "Uninstall"

    ; Remove registry keys
    DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\RPGAudioMixer"
    DeleteRegKey HKLM SOFTWARE\RPG_Audio_Mixer

    ; Remove files and uninstaller
    Delete $INSTDIR\rpgam.exe
    Delete $INSTDIR\uninstall.exe

    ; Remove shortcuts, if any
    Delete "$SMPROGRAMS\RPG Audio Mixer\*.*"

    ; Remove directories used
    RMDir "$SMPROGRAMS\RPG Audio Mixer"
    RMDir "$INSTDIR"

SectionEnd

Ant集成

我在我的Ant构建文件(build.xml)中有一些目标来处理上述内容。首先,我告诉Ant导入launch4j的Ant任务:

<property name="launch4j.dir" location="vendor/launch4j" />
<taskdef name="launch4j" 
    classname="net.sf.launch4j.ant.Launch4jTask"
    classpath="${launch4j.dir}/launch4j.jar:${launch4j.dir}/lib/xstream.jar" />

我接下来需要创建一个简单的目标来生成包装器可执行文件:

<target name="executable-windows" depends="jar" description="Create Windows executable (EXE)">
    <launch4j configFile="scripts/launch4j.xml" outfile="${exeFile}" />
</target>

另一个制作安装程序的目标:

<target name="installer-windows" depends="executable-windows" description="Create the installer for Windows (EXE)">
    <!-- Lay out files needed for building the installer -->
    <mkdir dir="${windowsLayoutDirectory}" />
    <copy file="${jarFile}" todir="${windowsLayoutDirectory}" />
    <copy todir="${windowsLayoutDirectory}/lib">
        <fileset dir="${libraryDirectory}" />
        <fileset dir="${windowsLibraryDirectory}" />
    </copy>
    <copy todir="${windowsLayoutDirectory}/icons">
         <fileset dir="${iconsDirectory}" />
    </copy>
    <copy todir="${windowsLayoutDirectory}" file="${exeFile}" />

    <mkdir dir="${windowsInstallerDirectory}" />

    <!-- Build the installer using NSIS -->
    <exec executable="vendor/nsis/makensis.exe">
        <arg value="/DVERSION=${version}" />
        <arg value="scripts/rpgam-setup.nsi" />
    </exec>
</target>

上半部分只是将安装程序所需的文件复制到临时位置,下半部分执行脚本使用这些文件来生成安装程序。


虽然我还没有实际尝试过,但它看起来非常完整。请投票支持这个答案! - Scott Bennett-McLeish
对于大多数业余软件应用程序来说,这可能太昂贵了 :) - willcodejavaforfood
首先是install4j.xml文件 - 嗯,这应该是launch4j.xml或其他什么吗? - Jonik

10
在我的公司,我们使用Launch4J来创建exe文件,并使用NSIS创建安装程序,适用于SWT应用程序。
多年来,我们在几个商业应用程序中都使用了它们,这对工作非常好。

7
也许你应该看一下 IzPack。几年前我创建了一个非常不错的安装程序,我敢打赌他们仍在改进它。它允许安装文档、二进制文件和一个可点击的链接来启动应用程序 IIRC

哇,开源的看起来仍然很活跃,而jsmooth似乎已经死了一年没有更新。 - willcodejavaforfood

4
我曾使用免费的Launch4J在 Windows 上为我的 Java 程序创建了一个自定义启动器。结合免费的NSIS 安装程序,你可以为你的 Windows 用户构建一个漂亮的软件包。 编辑:我没有看到你使用 SWT。不确定它是否也适用于 SWT,因为我只在我的应用程序中使用 Swing。

3

您有没有考虑使用C/C++编写一个小程序,只需调用CreateProcess来启动带有jar(或class)文件的Java VM?

您可以获取Visual C++ Express并轻松地组合起始程序。这将使添加友好的图标变得容易。


3
考虑将您的应用程序转换为Eclipse RCP。它是使用SWT编写的,Eclipse IDE 包含打包工具,可以生成所有主要平台的可执行文件。对于 Windows,它可以生成包含您的代码的 zip 或文件夹。为了获得通用的安装体验,建议使用 NSIS。实际上,eclipse 还有一个packages generator项目,可以创建所有平台的通用安装程序。

我考虑过Eclipse RCP,但它对于我的项目来说有点过重了,因为我的项目是一个轻量级的桌面博客发布工具。 - alexmcchessers
Eclipse RCP并不是很大。如果你只保留基本UI所需的必要类,并使你的项目仅依赖于org.eclipse.runtime.core和org.eclipse.ui,那么它的大小不到8 MB,而且你将获得一个良好的平台来管理你的依赖关系。 - Mario Ortegón

2

你想过使用Java Web Start吗?这里有一个针对使用Java Web Start部署SWT应用程序的教程。


1

现在你可以通过Netbeans完成此操作!这很容易且完美运行。请查看this Netbeans网站上的教程。


1

Install4J。虽然不免费,但非常值得。试用一下吧。


install4j非常擅长生成完全本地化的.exe Windows安装程序(它也支持其他目标平台)。此外,对于部署Java软件来说,它是一个很好的选择。更多关于它的使用体验可以参考:https://dev59.com/o3RA5IYBdhLWcg3w_C8w#786307 不过,它是商业工具,可能不适合原始提问者。 - Jonik

0

你考虑过使用Advanced Installer吗?

我经常用它来为Windows和Mac打包安装程序,无需脚本或Ant。全部都是图形界面,非常简单易懂。虽然不免费,但物有所值。

- 以管理员身份运行
- 文件关联
- 自定义安装主题+内置主题
- 打包JRE
- 安装位置
- 本地启动画面实现
- 甚至可以创建服务和安装事件
- 先决条件
- JRE最小版本和最大版本

还有很多其他功能。别误会,我与这些人没有任何联系...他们的应用程序只是太棒了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接