如何创建不需要Vista / Win7用户来安装Visual C ++可再发行组件的Windows可执行文件?

时间:2018-12-05 05:55:44

标签: c++ visual-studio dll

我已经编写了一个从Windows Vista到Windows 10的Java程序。

该程序在嵌入式Java运行时环境中运行,因此用户不必费力安装Java就可以正常工作。 该项目的目标是要下载用户体验->运行单个安装程序->运行程序并使之具有原生性。用户不需要其他步骤。

为了实现此目标,我需要用C ++编写一个本机可执行文件,该程序可以直接调用JVM(而不是通过调用java.exe),因此Windows Takbar功能固定可以正常工作-如果我使用可执行程序包装,例如launch4j在任何时候都将执行传递给java.exe,然后固定无法按预期的方式进行。我自己的可执行文件需要在运行期间保持运行状态,以便正确固定。

我已经编写了一个本地启动器C ++程序,该程序使用JNI通过jvm.dll而不是java.exe来调用Java虚拟机,并且可以正常工作。这是一个100行的填充码(此文章底部的代码)。它仅导入windows.h并使用以下功能:HINSTANCEGetProcAddressWinMain。它在运行时显式链接到嵌入式jvm.dll

但是,如果我使用Visual Studio 2017编译此填充程序,则生成的可执行文件取决于安装了Visual C ++ 2015 Redistributable的用户。如果没有,程序将显示错误消息“由于计算机缺少VCRUNTIME140.dll而无法启动”。

我尝试使用/ MT标志并通过在Visual Studio的“常规项目属性”页中选择“在静态库中使用MFC”来编译此程序。它没有改变;无论如何,我都会遇到相同的错误。

尽管Windows Vista / Windows 7上的许多用户已经安装了运行时,但有些可能没有,并且我对这个项目的优先考虑是从下载到安装到运行的流畅,无错误的用户体验。

我在项目中捆绑其他dll没有任何问题。如果这更有意义,我可以使用MinGW或Cygwin进行编译。我唯一想要的是从Vista到Windows 10的任何版本的Windows都有一定的download -> install -> run路径。

如何创建一个独立的可执行文件或可以与少数dll一起分发的可执行文件,使其在Vista和Windows的较新版本中是独立的?


最小的完整可验证示例: You can download a zip或通过以下步骤自行完成所有操作:

步骤1-初始化:创建文件夹josh-problem

步骤2-下载JRE:下载Windows 64 bit zip of Java 11并将其放入josh-problem/jre,以使josh-problem/jre的内容是名为{{1}的java文件夹。 },liblegaljmodsincludeconf等。

第3步-设置Java程序:创建bin。使其内容:

josh-problem/src/net/joshuad/test/Main.java

第4步-创建清单:创建包含一行内容的文件package net.joshuad.test; public class Main { public static void main(String[] args) { System.out.println ( "Hi from Java, launched via embedded jre, via native executable." ); } }

josh-problem\MANIFEST.MF

步骤5-编译并创建main.jar :导航至cmd.exe中的文件夹Main-Class: net.joshuad.test.Main 。运行以下命令:

  • josh-problem
  • jre\bin\javac.exe -d bin src\net\joshuad\test\Main.java

步骤6-确认jar正常工作:运行命令:

jre\bin\jar.exe cfm main.jar MANIFEST.MF -C bin .

您应该看到输出:“嗨,来自Java,是通过嵌入式jre通过本机可执行文件启动的。”

第7步-编译本机启动器在Visual Studio 2017中创建一个项目,并为其提供单个cpp文件,其源代码来自本文的最底部。添加到您的包括jre\bin\java.exe -jar main.jarjosh-problem\jre\include中。

步骤8-尝试运行-将输出可执行文件移至josh-problem\jre\include\win32。尝试在干净的Windows 7 Service Pack 1计算机上运行可执行文件。它将出现错误:“程序无法启动,因为您的计算机缺少VCRUNTIME140D.dll。”。

第9步-通过Java运行-在同一台干净的Windows 7计算机上,通过调用java.exe运行该程序,该程序可以运行。

josh-problem

步骤10-安装Visual C ++ Redistributable,然后重试我们的exe -在干净的Windows 7计算机上下载并安装2015 Visual C++ Redistributable。重试我们的可执行文件。可以。

**我应如何编译此代码,使其不需要Visual C ++可再发行组件?我知道这是可能的,因为我们只是演示了java.exe在做什么。如何使我的程序做到这一点?*

下载,我知道这个问题很棘手。为了方便起见,我完成了上述工作,并将其放入in a zip to download,其中包括jar,java源代码,C ++源代码和生成的可执行文件。您必须使用上面的链接将jre下载到jre文件夹;我不想创建一个巨大的拉链。

我还上传了我的visual studio project in a zip

win-launcher.cpp

jre\bin\java.exe -jar main.jar

3 个答案:

答案 0 :(得分:3)

您无需定位特定的SDK,只需将“ c ++”,“代码生成”,“运行时库”更改为“多线程”或“多线程调试”即可静态链接到Visual Studio运行时。这将使您的应用程序更大,但仅取决于Windows DLL。

答案 1 :(得分:2)

问题不是您编译的exe,而是您使用的jre版本。使用其他JRE版本或编译来自OpenJDK的自己的版本

enter image description here

由于DLL位于该库中,因此也可以将\jre\bin添加到库搜索路径中。

例如使用SetDllDirectoryA("jre\\bin")

答案 2 :(得分:1)

如果您的本机代码很小,并且仅使用基本的C标准库或Win32函数,则可以使用MinGW进行构建,MinGW与msvcrt.dll而不是msvcr1xx.dll进行CRT调用,因此不会依赖VC ++ DLL(如果使用C ++标准库功能,则使用-static标志进行构建以嵌入libstdc ++)。

否则,仅使用带有/MT标志的VC ++进行构建。您的可执行文件将变得更大,但这是一种更可移植的解决方案。