Как запустить командный файл из приложения Java?

107

В моем приложении Java я хочу запустить командный файл, который вызывает " scons -Q implicit-deps-changed build\file_load_type export\file_load_type"

Кажется, я даже не могу запустить командный файл. У меня нет идей.

Вот что у меня на Java:

Runtime.
   getRuntime().
   exec("build.bat", null, new File("."));

Раньше у меня был файл Python Sconscript, который я хотел запустить, но, поскольку это не сработало, я решил, что вызову скрипт через командный файл, но этот метод пока не сработал.

Амара
источник

Ответы:

172

Пакетные файлы не являются исполняемым файлом. Им нужно приложение для их запуска (например, cmd).

В UNIX файл сценария имеет в начале файла знак shebang (#!), Чтобы указать программу, которая его выполняет. Двойной щелчок в Windows выполняется проводником Windows. CreateProcessничего об этом не знает.

Runtime.
   getRuntime().
   exec("cmd /c start \"\" build.bat");

Примечание. С помощью start \"\"команды откроется отдельное командное окно с пустым заголовком, и в нем будут отображаться все выходные данные командного файла. Он также должен работать только с cmd / c build.bat, в этом случае вывод может быть прочитан из подпроцесса в Java, если это необходимо.

Пауло Гедес
источник
Для меня это говорит, что Windows не может найти "build.bat". Так куда мне положить этот файл? Или как мне указать путь. Какие-либо предложения?
nanospeck
1
скажем, у меня есть массив команд, а затем я выполняю итерацию этого массива для выполнения всех команд (от i = 0 до commands.length) {Runtime.getRuntime (). exec ("cmd / c start buil.bat"); } затем для каждой итерации (для каждой команды) открывается командное окно, что очевидно. Как этого избежать? Я имею в виду выполнение всех команд в одном окне.
viveksinghggits
1
У нас есть код, который напрямую вызывает "gradlew.bat", не помещая перед ним "cmd / c", и этот код каким-то образом работает. Так что я полагаю, что либо Java, либо Windows в какой-то момент устранили часть проблемы. Если мы попытаемся выполнить «gradlew», это не удастся, поэтому очевидно, что «.bat» все еще нужен в конце.
Trejkaz
Win+R(Время выполнения) может выполнять командные файлы напрямую.
Alex78191
21

Иногда время процесса выполнения потока превышает время ожидания потока JVM, это обычно происходит, когда процесс, который вы вызываете, требует некоторого времени для обработки, используйте команду waitFor () следующим образом:

try{    
    Process p = Runtime.getRuntime().exec("file location here, don't forget using / instead of \\ to make it interoperable");
    p.waitFor();

}catch( IOException ex ){
    //Validate the case the file can't be accesed (not enought permissions)

}catch( InterruptedException ex ){
    //Validate the case the process is being stopped by some external situation     

}

Таким образом, JVM остановится до тех пор, пока процесс, который вы вызываете, не будет выполнен, прежде чем он продолжит работу со стеком выполнения потока.

Хуан Карлос Альпизар
источник
20
Runtime runtime = Runtime.getRuntime();
try {
    Process p1 = runtime.exec("cmd /c start D:\\temp\\a.bat");
    InputStream is = p1.getInputStream();
    int i = 0;
    while( (i = is.read() ) != -1) {
        System.out.print((char)i);
    }
} catch(IOException ioException) {
    System.out.println(ioException.getMessage() );
}
Иша
источник
2
Было бы полезно прокомментировать этот код и рассказать нам, почему и что читает InputStream, и почему меня это волнует. Кроме того, код для пакетного файла работает нормально, но я не могу заставить его вызвать исключение ошибки.
Барух Атта,
2
Я бы с ума сошел, если бы в моем коде было такое запутанное имя переменной, как «есть».
Джон Фишер
14

Чтобы запускать командные файлы с использованием java, если вы об этом ...

String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);`

Это должно сработать.

Abbia
источник
10
На вопрос уже был дан ответ рабочим решением. Вы должны предлагать только те решения, которые, как вы знаете, работают, и описывать, почему, по вашему мнению, ваше решение может быть лучше.
Smamatti
12

ProcessBuilder - это способ Java 5/6 для запуска внешних процессов.

басовый
источник
2
Почему ProcessBuilder подходит для Java 5/6?
Дэн Политес,
2
Интересный выбор для воскрешения старого поста ... ProcessBuilder предлагает больше контроля, в частности, возможность легко перенаправить stderr на stdout. Я также считаю настройку более интуитивно понятной, но это личное предпочтение
basszero
10

Исполняемый файл, используемый для запуска пакетных скриптов, cmd.exeиспользует /cфлаг для указания имени командного файла для запуска:

Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "build.bat"});

Теоретически вы также должны иметь возможность запускать Scons таким образом, хотя я этого не тестировал:

Runtime.getRuntime().exec(new String[]{"scons", "-Q", "implicit-deps-changed", "build\file_load_type", "export\file_load_type"});

РЕДАКТИРОВАТЬ: Амара, вы говорите, что это не работает. Указанная вами ошибка - это ошибка, которую вы получите при запуске Java из терминала Cygwin в Windows; это то, что ты делаешь? Проблема в том, что у Windows и Cygwin разные пути, поэтому версия Java для Windows не найдет исполняемый файл scons на вашем пути Cygwin. Я могу объяснить дальше, если это окажется вашей проблемой.

Эли Кортрайт
источник
Спасибо. Это по-прежнему не работает - этот фрагмент кода даже не выполняется в моем приложении. Я попробую другой вариант, который вы представили. Еще раз спасибо.
Амара
Когда я пробую вторую альтернативу, я получаю следующую ошибку: Исключение в потоке «main» java.io.IOException: Невозможно запустить программу «scons»: Ошибка CreateProcess = 2, Система не может найти указанный файл
Амара
Нет, у меня нет терминала Cygwin. Я использую командный терминал Windows. Странно - не знаю, почему не сработало. Это меня полностью сбивает с толку.
Амара
3
Process p = Runtime.getRuntime().exec( 
  new String[]{"cmd", "/C", "orgreg.bat"},
  null, 
  new File("D://TEST//home//libs//"));

протестировано с jdk1.5 и jdk1.6

У меня это сработало, надеюсь, это поможет и другим. чтобы получить это, я боролся больше дней. :(

Сурен
источник
1
добавьте это ==> BufferedReader reader = new BufferedReader (новый InputStreamReader (p.getInputStream ())); Строка line = reader.readLine (); в то время как (строка! = ноль) {System.out.println (строка); line = reader.readLine (); }
Suren
2

Я была такая же проблема. Однако иногда CMD не запускал мои файлы. Вот почему я создаю temp.bat на своем рабочем столе, затем этот temp.bat будет запускать мой файл, а затем временный файл будет удален.

Я знаю, что это более крупный код, но сработал у меня на 100%, когда даже Runtime.getRuntime (). Exec () не удалось.

// creating a string for the Userprofile (either C:\Admin or whatever)
String userprofile = System.getenv("USERPROFILE");

BufferedWriter writer = null;
        try {
            //create a temporary file
            File logFile = new File(userprofile+"\\Desktop\\temp.bat");   
            writer = new BufferedWriter(new FileWriter(logFile));

            // Here comes the lines for the batch file!
            // First line is @echo off
            // Next line is the directory of our file
            // Then we open our file in that directory and exit the cmd
            // To seperate each line, please use \r\n
            writer.write("cd %ProgramFiles(x86)%\\SOME_FOLDER \r\nstart xyz.bat \r\nexit");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // Close the writer regardless of what happens...
                writer.close();
            } catch (Exception e) {
            }

        }

        // running our temp.bat file
        Runtime rt = Runtime.getRuntime();
        try {

            Process pr = rt.exec("cmd /c start \"\" \""+userprofile+"\\Desktop\\temp.bat" );
            pr.getOutputStream().close();
        } catch (IOException ex) {
            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);

        }
        // deleting our temp file
        File databl = new File(userprofile+"\\Desktop\\temp.bat");
        databl.delete();
Бен Йост
источник
1

Следующее работает нормально:

String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
бхарата
источник
что означает / c?
Amal lal TL
0

Этот код выполнит две команды command.bat, которые существуют в пути C: / folder / folder.

Runtime.getRuntime().exec("cd C:/folders/folder & call commands.bat");
رامي عبد الله
источник
0

Чтобы расширить anwser @ Isha, вы можете просто сделать следующее, чтобы получить возвращенный вывод (пост-факто, а не в реальном времени) запущенного скрипта:

try {
    Process process = Runtime.getRuntime().exec("cmd /c start D:\\temp\\a.bat");
    System.out.println(process.getText());
} catch(IOException e) {
    e.printStackTrace();
}
Лапша Смерти
источник