Процесс p = Runtime.getRuntime (). Exec ("cmd / c start batch.bat");
Чтобы дождаться завершения пакетного файла (выхода), который вы удаляете«начало» после /c
./c
указывает cmd.exe возвращаться после завершения cmd, однако это нужно, однако «запуск» означает запуск нового процесса cmd.exe для выполнения командного файла.На этом этапе запущенный cmd.exe завершен и завершает работу.Возможно, это не то, что вам нужно.
Любой из двух приведенных ниже фрагментов кода запустит пакетный файл и предоставит вам объект Process, который вам понадобится.
Process p = Runtime.getRuntime().exec("cmd /c batch.bat");
Или
ProcessBuilder pb= new ProcessBuilder ("cmd", "/c", "batch.bat");
Process p = pb.start ();
Теперь, когда у вас есть объект Process, у вас есть несколько способов ожидания завершения обработки вашего пакетного файла.
Самый простой способ - это.waitFor ()
int batchExitCode = -1;
try {
batchExitCode = p.waitFor ();
} catch (InterruptedException e) {
// kill batch and re-throw the interrupt
p.destroy (); // could also use p.destroyForcibly ()
Thread.currentThread ().interrupt ();
}
Вы также можете использовать waitFor(long timeout, TimeUnit unit)
или p.isAlive()
, если они лучше соответствуют вашим потребностям.
Предупреждение Если ваша партия будет выводитьсябольшая часть данных (вероятно, более 1024 символов, может быть меньше) для stdout и / или stderr вашей программе должна каким-то образом обрабатывать эти данные, в противном случае канал (ы) между вашей программой и пакетным процессом заполнятся, ипакетный файл будет зависать в ожидании места в трубе для добавления новых символов, и пакетный файл никогда не вернется.
Эта проблема изначально привела меня к переполнению стека в этот раз.У меня было 17 000+ команд в командном файле, и каждая команда генерировала 300+ символов для стандартного вывода, а любые ошибки при выполнении команды генерировали 1000+ символов.
Некоторые способы решения этой проблемы:
@echo off
в качестве 1-й строки в пакетном файле, при этом процесс cmd не будет отображать каждую команду в пакетном файле.Если ваш пакетный файл не генерирует никаких других выходных данных для stdout или stderr, все готово.
Если одна или несколько команд в пакетном файле могут или могут генерировать много stdout и/ или вывод stderr, тогда вы должны обрабатывать эти данные самостоятельно.
Если вы используете "Runtime.getRuntime (). exec", у вас есть только один способ обработать это,получить InputStreams для stdout и stderr пакетного файла, вызвав:
InputStream outIS = p.getInputStream (); // this gets the batch file's stdout
InputStream errIS = p.getErrorStream (); // this gets the batch file's stderr
Теперь вам нужно прочитать каждый из InputStreams (только когда у них есть данные, или вы будете ждать, пока вы их сделаете).Предполагая, что вы получаете намного больше данных от одного из InputStreams, чем от другого, вы почти уверены, что повесили пакетный файл.Существуют способы чтения нескольких потоков без зависания, однако они выходят за рамки моего и без того слишком длинного ответа.
Если вы используете ProcessBuilder pb= new ProcessBuilder ("cmd", "/c", "batch.bat");
(и это главная причинадля этого) у вас есть намного больше доступных вариантов, так как вы можете попросить объединить stdout и stderr pb.redirectErrorStream (true);
, проще обрабатывать один InputStream без блокировки, или вы можете перенаправить stdout и stderr в файлы (могут работать нулевые файлы)в Windows определенно в Unix), поэтому ваша программа не должна их обрабатывать.
Не забывайте, что если ваш пакетный файл читает данные из stdin, вы должны также справиться с этим,Это поддерживается в Process и с дополнительными параметрами в ProcessBuilder .