进程 p = Runtime.getRuntime().exec("cmd /c start batch.bat");
要等待批处理文件完成(退出),请删除/c 之后的“开始”。
/c 告诉 cmd.exe 在 cmd 完成后返回,这是你想要的,但是,“start”意味着启动一个新的 cmd.exe 进程来执行批处理文件。至此你启动的 cmd.exe 完成并退出。可能不是你想要的。
下面的两个代码 sn-ps 中的任何一个都将使批处理文件运行并为您提供所需的 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() 更能满足您的需求,您也可以使用它们。
警告如果您的批处理要向 stdout 和/或 stderr 输出大量数据(可能超过 1024 个字符,也可能更少),您的程序需要以某种方式处理这些数据,否则,您的程序和批处理之间的管道将填满,批处理文件将挂起,等待管道中的空间添加新字符,并且批处理文件将永远不会返回。
这就是这次最初把我带到 Stack Overflow 的问题。我在一个批处理文件中有 17,000 多个命令,每个命令生成 300 多个字符到标准输出,执行命令的任何错误都会生成 1000 多个字符。
解决这个问题的一些方法:
@echo off 作为批处理文件的第一行,这样 cmd 进程将不会回显批处理文件中的每个命令。如果您的批处理文件没有向 stdout 或 stderr 生成任何其他输出,那么您就完成了。
如果批处理文件中的一个或多个命令可以或可能生成大量标准输出和/或标准错误输出,那么您必须自己处理这些数据。
-
如果您使用“Runtime.getRuntime().exec”,您只有一种方法来处理这个问题,那就是通过调用获取批处理文件的 stdout 和 stderr 的 InputStreams:
InputStream outIS = p.getInputStream (); // this gets the batch file's stdout
InputStream errIS = p.getErrorStream (); // this gets the batch file's stderr
现在您必须读取每个 InputStream(仅当它们有数据时,否则您将等到有数据时)。假设您从其中一个 InputStreams 获得的数据比另一个多得多,您几乎可以肯定会挂起批处理文件。有一些方法可以在不挂起的情况下读取多个流,但是,它们超出了我已经过长的答案的范围。
1234563处理一个 InputStream 而不阻塞,或者您可以将 stdout 和 stderr 重定向到文件(空文件可能在 Windows 上肯定在 Unix 上工作),因此您的程序不必处理它们。
不要忘记,如果您的批处理文件从标准输入读取数据,您也必须处理它。这在 Process 中受支持,并且在 ProcessBuilder 中提供更多选项。