1

所以我的问题是,我制作了某种启动器并编写了一个方法,如果你点击“播放”按钮就会被调用。

private void PlayButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
    try 
    {
        new ProcessBuilder("src/calc.exe").start(); 
    } 
    catch (IOException ex) 
    {
        Logger.getLogger(Launcher.class.getName()).log(Level.SEVERE, null, ex);
    }
}  

正在执行的文件只是 Windows 中计算器的副本,位于我项目的 src 文件夹中。(路径是“src/calc.exe”)

只要我不将我的 netbeans 项目文件编译成 JAR 文件,一切都可以正常工作。

如果我运行 JAR 文件并单击播放按钮 - 没有任何反应。

我真的希望你能告诉我如何解决这个问题。

(PS:calc.exe并不总是要运行的程序的名字,文件名是由一个.ini决定的。calc.exe只是用来测试程序的。)

4

2 回答 2

2

首先,一些背景:

  • 文件是一个JAR存档,一个包含 Java 字节码和其他可以从 JVM 内部使用的资源的包(压缩或未压缩)。
  • 文件是可执行的EXE二进制文件,只能被 Windows/MS-DOS 家族操作系统理解。

当您运行程序而不将其打包到 JAR 文件中时,所有资源(类文件和可执行文件)都可以从操作系统访问。Windows 将启动 JVM,并从那里通过ProcessBuilder指示操作系统调用一个可执行文件,该文件可在与执行执行指令的类相关的路径中访问。直到那里,一切都很好,正如你所说,它有效。

但是,当您将 Java 类和可执行文件打包到 JAR 中并调用 JAR 时,操作系统将无法再访问其内容。正在发生的事情是操作系统将启动 JVM 并处理 JAR 文件以找到可执行类(您在其中调用ProcessBuilder. 现在,您可以从该类文件中指示操作系统启动一个可执行文件,该可执行文件位于相对于 JAR 文件的路径中,而不是相对于执行调用指令的类文件。由于 EXE在 JAR 文件中而不是相对于它,因此执行失败,因为它找不到可执行文件。

之所以这样,是因为操作系统不会在 JAR 文件中查找特定文件,对于操作系统而言,JAR 文件只是一个文件,而不是文件夹,因此它将忽略其内容。

因此,结论是,由于您正在调用操作系统以在另一个文件中执行特定操作,因此必须将该文件放在 JAR 之外并放在该 JAR 的相对路径中。

如果出于某种原因您坚持将您的 EXE 打包到 JAR 中,那么您需要在调用ProcessBuilder到临时文件夹之前将其提取到 JAR 之外并ProcessBuilder使用该新路径调用。

于 2013-08-09T13:53:58.233 回答
1

这是一个敏感的话题。

谁评论说 JAR 不能做到这一点是错误的。相反,除非作者通过Oracle签名和验证,否则是applet没有这样的权限。

你说这一切都很好,除非你把它放在一个 JAR 中。这可能是因为您的 URI 与 Windows 文件系统相关。

无论引用周围的包装如何,通常获取文件的方法是执行以下操作:

    MainClass.class.getResourceAsStream(file);

静态 getResourceAsStream 将解析可用的相对路径和绝对路径,如果您将“src/calc.exe”放在这里,它应该可以工作。

另一个建议是线程打开进程。如果您将程序作为单线程,Java 程序将挂起,直到外部进程消失并清理干净。

于 2013-08-09T13:35:15.167 回答