我是 Java 编程新手,但通常熟悉一切工作原理。我希望能够将 jar 文件和 jre 都放入 windows 可执行文件(exe)中,这样当我分发它时,客户端就不需要安装 JRE。我应该使用什么程序?
我有launch4j,它似乎完全符合我的要求,但是当我尝试运行该应用程序时,我得到“此应用程序配置为使用捆绑的Java运行时环境,但运行时丢失或损坏。”
我希望我的应用程序只是一个可运行的 exe,而不是安装程序。至少,谁能告诉我如何正确地将 JRE 与 launch4j 捆绑在一起?
我可以捆绑 JRE 的唯一方法是使用Launch4J和Inno Setup Compiler。
首先,在与输出文件 (.exe) 相同的目录中创建一个jre6
文件夹(例如)。
然后将 JRE 从您的系统复制到您的jre6文件夹中。
然后打开 Launch4J 并设置Bundled JRE 路径- 只需输入jre6
. 然后单击 Build 按钮(显然,在您输入所有其他参数之后 - 但您需要在JRE选项卡本身上输入的唯一值是Bundled JRE 路径值。)
我原以为这会起作用,但是如果您随后将 .exe 移动到新位置(因此它不再与您的jre6文件夹位于同一位置),您会得到此应用程序配置为使用捆绑的 Java 运行时环境,但是当您尝试运行应用程序时,运行时丢失或损坏错误...
我整天都在玩这个,我无法让Launch4J将 JRE 包含在 .exe 文件中。在我看来真的很差,因为他们的文档似乎根本没有提到这个问题。
所以我要解决的是使用Inno Setup Compiler (ISC)。此应用程序用于将您的 .exe 包装为 Windows Installer 文件。所以我在 ISC 脚本中添加了一个设置,将 JRE 复制到安装程序包中。我添加到脚本中的行(在该[Files]
部分中)是:
Source: "M:\Netbeans\MyApp\jre6\*"; DestDir: "{app}\jre6\"; Flags: recursesubdirs createallsubdirs
...一些解决方法,但它成功了。
重复上述所有步骤,您应该被排序。
将 jre 打包为 lanch4j 打包的 exe 的简单方法是使用 wrap。
warp-packer --arch windows-x64 --input_dir mycrt --exec run.bat --output single.exe
然后在启动 exe 时停止 cmd 窗口。
editbin /subsystem:windows
经线:https ://github.com/dgiagio/warp
editbin : 由 VS 安装
演示:
用于 Inno Setup 的捆绑 JRE 解决方案
为了使用应用程序 jar 实现捆绑的 JRE 解决方案,我创建了一个 Inno Setup 脚本:
1)将JRE复制到安装exe中
2) 执行等效的终端命令: java -jar myjar.jar 使用捆绑的 JRE
首先我复制JRE:
#define MyJREPath "C:\Program Files\Java\jre1.8.0_191"
[Files]
Source: "{#MyJREPath}\*"; DestDir: "{app}\runtime\jre\"; \
Flags: ignoreversion recursesubdirs createallsubdirs;
我遵循此处显示的目录结构约定:https ://docs.oracle.com/javase/8/docs/technotes/guides/deploy/self-contained-packaging.html
运行 java -jar myjar.jar 的等效项:
[Run]
Filename: "{app}\runtime\jre\bin\javaw.exe"; Parameters: " -jar myjar.jar"; \
WorkingDir: "{app}\app\"; \
Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; \
Flags: postinstall skipifsilent
(nb java.exe 使用终端运行,javaw.exe 不使用终端运行)
桌面快捷方式需要有正确的文件名、参数和工作目录:
[Icons]
Name: "{commondesktop}\{#MyAppName}"; \
IconFilename: "{app}\app\{#MyAppIcoName}"; \
Filename: "{app}\runtime\jre\bin\javaw.exe"; \
Parameters: " -jar myjar.jar"; \
WorkingDir: "{app}\app\"; \
Tasks: desktopicon
[Tasks]
Name: "desktopicon"; \
Description: "{cm:CreateDesktopIcon}"; \
GroupDescription: "{cm:AdditionalIcons}"; \
Flags: unchecked
锦上添花,为了让我的脚本同时处理捆绑的 JRE 和非捆绑的选项,我使用预处理器 IF 语句(在每个脚本部分中重复)来测试脚本是否有空的 MyJREPath。如果 MyJREPath 不为空,因此需要捆绑的 JRE 解决方案,我使用上面的编码;或者,如果不需要捆绑解决方案,那么我使用更多“正常”编码显示 Inno Setup 示例或由他们的向导生成。这是 IF 语句:
#if MyJREPath != ""
; bundled JRE required
#else
; bundled JRE not required
#endif
这是我的大部分脚本放在一起:
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
; some more #defines here
#define MyAppExeName "javaw.exe"
#define MyJREPath "C:\Program Files\Java\jre1.8.0_191"
;#define MyJREPath ""
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId=XXXXXXXXXX
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
DefaultGroupName={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyDefaultDirName}
DisableProgramGroupPage=yes
LicenseFile={#MyInnoSetupDir}\system\{#MyLicenseFile}
OutputDir={#MyInnoSetupDir}
#if MyJREPath != ""
; run app with bundled JRE
OutputBaseFilename={#MyAppName}-{#MyAppVersion}-bundledJRE-setup
#else
; run app without bundled JRE
OutputBaseFilename={#MyAppName}-{#MyAppVersion}-setup
#endif
SetupIconFile={#MyInnoSetupDir}\{#MyAppIcoName}
Compression=lzma
SolidCompression=yes
AppComments={#MyAppName}
AppCopyright={#MyAppCopyright}
UninstallDisplayIcon={#MyInnoSetupDir}\{#MyAppIcoName}
UninstallDisplayName={#MyAppName}
WizardImageStretch=No
WizardSmallImageFile={#MyInnoSetupDir}\{#MyAppBmpName}
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
;Name: "german"; MessagesFile: "compiler:Languages\German.isl"
[Tasks]
Name: "desktopicon"; \
Description: "{cm:CreateDesktopIcon}"; \
GroupDescription: "{cm:AdditionalIcons}"; \
Flags: unchecked
Name: "quicklaunchicon"; \
Description: "{cm:CreateQuickLaunchIcon}"; \
GroupDescription: "{cm:AdditionalIcons}"; \
Flags: unchecked; OnlyBelowVersion: 0,6.1
[Files]
; bundle JRE if required
#if MyJREPath != ""
Source: "{#MyJREPath}\*"; DestDir: "{app}\runtime\jre\"; \
Flags: ignoreversion recursesubdirs createallsubdirs;
#endif
; copy jar and all files
Source: "{#MyInnoSetupDir}\*"; DestDir: "{app}\app\"; \
Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
#if MyJREPath != ""
; set up icons with bundled JRE
Name: "{commonprograms}\{#MyAppName}"; \
IconFilename: "{app}\app\{#MyAppIcoName}"; \
Filename: "{app}\runtime\jre\bin\{#MyAppExeName}"; \
Parameters: " -jar {#MyJarName}"; \
WorkingDir: "{app}\app\"
Name: "{commondesktop}\{#MyAppName}"; \
IconFilename: "{app}\app\{#MyAppIcoName}"; \
Filename: "{app}\runtime\jre\bin\{#MyAppExeName}"; \
Parameters: " -jar {#MyJarName}"; \
WorkingDir: "{app}\app\"; \
Tasks: desktopicon
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; \
IconFilename: "{app}\app\{#MyAppIcoName}"; \
Filename: "{app}\runtime\jre\bin\{#MyAppExeName}"; \
Parameters: " -jar {#MyJarName}"; \
WorkingDir: "{app}\app\"; \
Tasks: quicklaunchicon
#else
; set up icons without bundled JRE
Name: "{commonprograms}\{#MyAppName}"; \
IconFilename: "{app}\app\{#MyAppIcoName}"; \
Filename: "{app}\app\{#MyJarName}"; \
WorkingDir: "{app}\app\"
Name: "{commondesktop}\{#MyAppName}"; \
IconFilename: "{app}\app\{#MyAppIcoName}"; \
Filename: "{app}\app\{#MyJarName}"; \
WorkingDir: "{app}\app\"; \
Tasks: desktopicon
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; \
IconFilename: "{app}\app\{#MyAppIcoName}"; \
Filename: "{app}\app\{#MyJarName}"; \
WorkingDir: "{app}\app\"; \
Tasks: quicklaunchicon
#endif
[Run]
#if MyJREPath != ""
; run app with bundled JRE
Filename: "{app}\runtime\jre\bin\{#MyAppExeName}"; Parameters: " -jar {#MyJarName}"; \
WorkingDir: "{app}\app\"; \
Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; \
Flags: postinstall skipifsilent
#else
; run app without bundled JRE
Filename: "{app}\app\{#MyJarName}"; \
WorkingDir: "{app}\app\"; \
Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; \
Flags: shellexec postinstall skipifsilent
#endif
希望这可以帮助。
我从来没有使用过 Launch4J 产品,祝它配置正确。
看起来你可以去 Sourceforge 上的论坛获取其他提示
其他建议:
我从 IBM (Websphere) 和 Oracle 看到的大多数产品只是在安装目录下提取一个 JRE,并配置启动批处理命令以使用已安装的 JRE。本质上,JRE 和您的 jar 文件将一次性安装。
安装 exe 通常会检查它是否已经安装,如果发现它已经存在则跳过该步骤。这对于仅升级 jar 文件很有用。
本地安装还解决了客户安装自己的 JRE 的问题,这些 JRE 可能不兼容或包含错误。这样您就可以处理已知的 JRE 版本。
如果您的应用程序没有图形组件,则 excelsior 路线是可以的(已经有一段时间了,该限制可能已经改变)。还有其他限制,但您最好将 JRE 与您的代码一起分发到单个可执行安装程序中。
JDK 7 Update 6 中的 JDK 随附的 Java Packager 是将 JRE 与您的代码一起嵌入到本机可执行文件中 的官方方式。一些maven插件似乎打包了主要平台打包生成本机可执行文件的任务。
从 JDK11 需要根据java-packager-with-jdk11下载 java 打包程序,女巫演示使用 gradle 进行打包
另一种方法可能是构建一个带有约束的GraalVM Native 映像,以使用不受支持的反射来查找库的替代方案。
很容易将 jre 捆绑到 launch4j 中。
只需将 jre 复制到相同的输出文件夹中
在bundle jre环境文本框中,只给jre文件夹本身
在环境变量文本框中(在下面的同一页中),给出直到 bin
然后创建exe ..它在机器中没有jre的情况下按预期工作。
谢谢
看来您需要本机代码编译器。这些编译器生成不需要 JRE 的本机代码。
检查这篇文章 - https://www.excelsior-usa.com/articles/java-to-exe.html#aot。
launch4j 不能顺利运行有几个原因。部分原因是:
1) 用户不要以管理员身份运行应用程序
2) 用户没有正确设置图标图像。必须严格.ico
你所要求的并不容易做到(如果它完全可行的话。)如果我是你,我会考虑创建一个可执行的 JAR 文件:
另一种选择是使用 Java Web Start。这是假设您使用的是现代浏览器,JNLP 将自动提示用户安装正确版本的 Java。
http://docs.oracle.com/javase/tutorial/deployment/webstart/index.html