Как запустить команду Ant через Java-программу?

Я хочу запустить простую команду ant -v через Java-программу. После поиска я пришел к выводу, что знаю, что мне нужно использовать shell вместо execute, так как ant на самом деле не является exe-форматом. У меня есть программа, которая работает для выполнения простой команды JAVAC, но муравей никогда не работает. Вот как выглядит мой код.

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

Причиной указания всего пути является то, что если я не получаю файл, файл не найден. Любая идея о том, как заставить это работать??

6 ответов

Решение

Ряд вещей прыгает на меня.

  1. ant команда должна быть ant.bat под окнами
  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, с которым 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");

Муравей написан на 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. Круто не так ли?

Для меня главное преимущество заключается в том, что вы можете лучше контролировать выполнение (например, легко узнать, что-то не получилось), и, конечно, можно получить результат, который сгенерирует скрипт.

В дополнение к ответу Аникета, чтобы сделать вещи еще проще:

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

Пытаться

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

Параметры к исполняемому файлу должны быть переданы отдельно:

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

В вашей попытке исполняемый файл буквально ant -v (то есть с пробелом в имени файла и заканчивая тире v).

Я бы пропустил файл bat и сразу запустил флягу

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

Но, как предлагается в других ответах, вы, вероятно, получите лучший результат, вызвав Java-интерфейс ant напрямую, а не используя внешний процесс. Учитывая ваш пример в вопросе использует -v Я предполагаю, что вы пытаетесь захватить что-то из подробного вывода сборки. Если вы вызываете муравей через его API, вы можете зарегистрировать слушателя на Project и ant будет доставлять сообщения журнала непосредственно вашему слушателю, а не анализировать их из вывода процесса.

Другие вопросы по тегам