How to run ant command through java program?

2019-04-17 03:33发布

问题:

I want to run a simple ant -v command through a java program. After searching, I came to a point where I know I have to use shell execute instead of process, since ant is not really an exe format. I have a program that works for executing simple JAVAC command, but ant never works. Here is what my code looks like.

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

I get following exception when I run this

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

The reason for specifying the whole path is, if I don't I get file not found error. Any idea on how to get this working??

回答1:

A number of things jump out at me.

  1. The ant command should be ant.bat under windows
  2. You should separate the command from the arguments, so that each argument represents a separate String. This greatly reduces the complexity of arguments that contain spaces, for example...
  3. You should really use ProcessBuilder, it will reduce the complexity of using Process

For example...

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();
}

I should also point out that ant is a linux/unix shell script, which Windows won't know what to do with ;)

Updated

I've tested this using Windows 7 and Java 7, works just fine

I've tested this using Windows 7 and Java 6, works just fine...

If you do continue to have issues running the ant.bat directly, then you will need run the batch file via the command processor

ProcessBuilder pb = new ProcessBuilder(
    "cmd",
    "/c",
    "D:\\installs\\apache-ant-1.9.2\\bin\\ant.bat", 
    "-v");


回答2:

Ant is written in Java. Why not directly call its classes in the same Java process instead of launching an external process?

There was an interesting answer posted here.

Here is the code as posted on that answer:

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());

It will executed the default target of the build.xml file. Cool isn't it?

For me, the main advantage is that you can control the execution better (you can easily know if something failed for example) and it is of course possible to get the output the script would generate.



回答3:

Try

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);

You can also do the following

ProcessBuilder pb = new ProcessBuilder("D:\\installs\\apache-ant-1.9.2\\bin\\ant -v", "-v");
Process p = pb.start();


回答4:

In addition to Aniket's answer, to make things even simplier:

Runtime.getRuntime().exec("D:\\installs\\apache-ant-1.9.2\\bin\\ant", new String[]{"-v"});


回答5:

Parameters to the executable must be passed in separately:

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

In your attempt, the executable file is literally ant -v (ie with a space in the filename and ending with dash v).



回答6:

I would skip the bat file and run the launcher jar directly

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();

But as suggested in other answers you'll probably get a better result by calling ant's Java API directly rather than using an external process. Given your example in the question uses -v I presume you're trying to capture something from the verbose output of the build. If you invoke ant via its API you can register a listener on the Project and ant will deliver log messages directly to your listener rather than you having to parse them out of the process output.