【问题标题】:How to execute a program within a Jar file如何在 Jar 文件中执行程序
【发布时间】:2013-08-09 22:02:07
【问题描述】:

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

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 文件并单击播放按钮 - 没有任何反应。

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

(P.S.: calc.exe 并不总是要运行的程序的名称。文件名由 .ini 确定。 calc.exe 仅用于测试程序。)

【问题讨论】:

  • 我认为默认情况下 JAR 文件没有该权限。
  • @LeventeKurusa:您可能正在考虑小程序。我怀疑这与许可有什么关系。
  • 是的,我不知何故最终相信这完全是关于小程序的。对不起,我的眼睛变老了或其他什么:o
  • Jonas:你的日志文件有数据吗?另外,您知道您应该在后台线程上运行该进程,对吧?
  • Jonas:这是什么:... ("src/calc.exe").start;我想你忘记了什么。

标签: java jar processbuilder


【解决方案1】:

首先,一些上下文:

  • 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

【讨论】:

  • 谢谢(:这对我很有帮助。我现在使用 MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());获取路径,然后添加我要启动的程序的名称。它有效! (:再次;非常感谢!
【解决方案2】:

这是一个敏感的话题。

任何评论 JAR 无法做到这一点的人都是错误的。反之,除非作者通过Oracle签名验证,否则是applet没有这样的权限。

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

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

    MainClass.class.getResourceAsStream(file);

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

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

【讨论】:

  • 当然,您需要使用 InputStreamReader,它可能包装在一个便利类中,例如 BufferedReader,以便从文件中获取数据。
  • 问题是我只想启动文件而不是从中读取。
  • 是的,您仍然可以使用它。可能更好的是同一层次结构中的方法 getResource,因为您可以将其读入 File 类,然后将其转换为 Process。
猜你喜欢
  • 2014-12-31
  • 2011-06-23
  • 2013-02-07
  • 1970-01-01
  • 1970-01-01
  • 2011-08-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多