0

我想通过 java 程序运行一个简单的 ant -v 命令。搜索后,我知道我必须使用 shell 执行而不是进程,因为 ant 并不是真正的 exe 格式。我有一个程序可以执行简单的 JAVAC 命令,但 ant 从来没有工作过。这是我的代码的样子。

Runtime runtime = Runtime.getRuntime() ;  
Process shellProcess = runtime.exec("D:\\installs\\apache-ant-1.9.2\\bin\\ant -v") ;
shellProcess.waitFor() ;

运行此程序时出现以下异常

Exception in thread "main" java.io.IOException: Cannot run program "D:\installs\apache-ant-1.9.2\bin\ant": CreateProcess error=193, %1 is not a valid Win32 application
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
at java.lang.Runtime.exec(Runtime.java:615)
at java.lang.Runtime.exec(Runtime.java:448)
at java.lang.Runtime.exec(Runtime.java:345)
at com.check.SystemCheck.main(SystemCheck.java:14)
Caused by: java.io.IOException: CreateProcess error=193, %1 is not a valid Win32 application

指定整个路径的原因是,如果我不指定文件未找到错误。关于如何使它工作的任何想法?

4

6 回答 6

3

有很多事情在我身上跳出来。

  1. ant命令应该ant.bat在windows下
  2. 您应该将命令与参数分开,以便每个参数代表一个单独的String. 这大大降低了包含空格的参数的复杂性,例如...
  3. 你真的应该使用ProcessBuilder,它会降低使用的复杂性Process

例如...

ProcessBuilder pb = new ProcessBuilder(
    "D:\\installs\\apache-ant-1.9.2\\bin\\ant.bat", 
    "-v");
pb.redirectError();
// This should point to where your build.xml file is...
pb.directory(new File("C:/"));
try {
    Process p = pb.start();
    InputStream is = p.getInputStream();
    int in = -1;
    while ((in = is.read()) != -1) {
        System.out.print((char) in);
    }
    int exitValue = p.waitFor();
    System.out.println("Exited with " + exitValue);
} catch (Exception ex) {
    ex.printStackTrace();
}

我还应该指出,这ant是一个 linux/unix shell 脚本,Windows 不知道如何处理它;)

更新

我已经使用 Windows 7 和 Java 7 对此进行了测试,效果很好

我已经使用 Windows 7 和 Java 6 对此进行了测试,效果很好......

如果您在ant.bat直接运行时仍然遇到问题,那么您将需要通过命令处理器运行批处理文件

ProcessBuilder pb = new ProcessBuilder(
    "cmd",
    "/c",
    "D:\\installs\\apache-ant-1.9.2\\bin\\ant.bat", 
    "-v");
于 2013-08-23T06:14:26.173 回答
3

Ant 是用 Java 编写的。为什么不在同一个 Java 进程中直接调用它的类,而不是启动一个外部进程呢?

这里发布了一个有趣的答案。

这是该答案上发布的代码:

File buildFile = new File("build.xml");
Project p = new Project();
p.setUserProperty("ant.file", buildFile.getAbsolutePath());
p.init();
ProjectHelper helper = ProjectHelper.getProjectHelper();
p.addReference("ant.projectHelper", helper);
helper.parse(p, buildFile);
p.executeTarget(p.getDefaultTarget());

它将执行 build.xml 文件的默认目标。很酷不是吗?

对我来说,主要优点是您可以更好地控制执行(例如,您可以轻松知道是否发生了故障),当然也可以获得脚本生成的输出。

于 2013-08-23T08:34:27.280 回答
0

尝试

ArrayList<String> argList = new ArrayList<String>();
argList.add("-v");
String[] args = argList.toArray(new String[argList.size()]);
Runtime.getRuntime().exec("D:\\installs\\apache-ant-1.9.2\\bin\\ant", args);

您还可以执行以下操作

ProcessBuilder pb = new ProcessBuilder("D:\\installs\\apache-ant-1.9.2\\bin\\ant -v", "-v");
Process p = pb.start();
于 2013-08-23T06:11:06.873 回答
0

除了 Aniket 的回答,为了让事情变得更简单:

Runtime.getRuntime().exec("D:\\installs\\apache-ant-1.9.2\\bin\\ant", new String[]{"-v"});
于 2013-08-23T06:15:02.577 回答
0

可执行文件的参数必须单独传入:

Runtime.getRuntime().exec("D:\\installs\\apache-ant-1.9.2\\bin\\ant", "-v");

在您的尝试中,可执行文件是字面意思ant -v(即文件名中有一个空格并以破折号 v 结尾)。

于 2013-08-23T06:15:07.437 回答
0

我会跳过 bat 文件并直接运行启动器 jar

File java = new File(new File(new File(
    System.getProperty("java.home"), "bin"), "java");
File antHome = new File("path to ant installation");
File launcher = new File(new File(antHome, "lib"), "ant-launcher.jar");
ProcessBuilder pb = new ProcessBuilder(
    java.getAbsolutePath(),
    "-jar",
    launcher.getAbsolutePath(),
    "-v");
pb.directory(dirContainingBuildXml);
Process p = pb.start();

但正如其他答案中所建议的那样,通过直接调用 ant 的 Java API 而不是使用外部进程,您可能会获得更好的结果。鉴于您在问题中使用的示例,-v我认为您正在尝试从构建的详细输出中捕获某些内容。如果您通过其 API 调用 ant,您可以在 ant 上注册一个侦听器,Project并且 ant 会直接将日志消息传递给您的侦听器,而不是您必须将它们从流程输出中解析出来。

于 2013-08-23T08:34:48.230 回答