我读到的所有内容都表明,在java程序中调用批处理文件的唯一方法是执行以下操作:
Process p = Runtime.getRuntime().exec("cmd /c start batch.bat");
据我所知,这创建了一个运行CMD.exe的进程,而CMD.exe又创建了一个运行批处理文件的进程。但是,CMD.exe进程在实例化批处理文件进程后似乎退出。
如何在退出CMD流程之前确认批处理文件已完成?
答案 0 :(得分:2)
您可以尝试在cmd / c之后不使用“start”命令启动批处理,因为“start.exe”会为batch.bat创建一个新进程。
Process p = Runtime.getRuntime().exec("cmd /c batch.bat");
这应该是适合您的正确形式。
答案 1 :(得分:2)
jeb说了什么,或尝试将/wait
参数传递给start
。这应该导致start
等待批处理完成。首先在命令行上尝试 - 比重建Java应用程序更快。
答案 2 :(得分:1)
从cmd /?
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
因此你需要的是:
Process p = Runtime.getRuntime().exec("cmd /k start batch.bat");
答案 3 :(得分:1)
进程p = Runtime.getRuntime()。exec(" cmd / c start batch.bat");
要等待批处理文件完成(退出),请删除" start"在/c
之后。
{} {}告诉cmd.exe在cmd完成时返回,但是,这就是" start"表示启动新的cmd.exe进程以执行批处理文件。此时,您启动的cmd.exe已完成并退出。可能不是你想要的。
以下两个代码段中的任何一个都将运行批处理文件,并为您提供所需的Process对象。
/c
或者
Process p = Runtime.getRuntime().exec("cmd /c batch.bat");
现在您有了一个Process对象,您可以通过多种方式等待批处理文件完成。
最简单的方法是.waitFor()
ProcessBuilder pb= new ProcessBuilder ("cmd", "/c", "batch.bat");
Process p = pb.start ();
如果他们更好地满足您的需求,您也可以使用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)
。
警告如果您的批处理要向stdout和/或stderr输出大量数据(可能超过1024个字符,可能更少),您的程序需要以某种方式处理此数据,否则,程序和批处理过程之间的管道将被填满,批处理文件将挂起,等待管道中的空间添加新字符,批处理文件将永远不会返回。
这次最初将我带到Stack Overflow的问题。我在批处理文件中有17,000多个命令,每个命令为stdout生成300多个字符,执行命令的任何错误都会生成1000多个字符。
解决此问题的一些方法:
p.isAlive()
作为批处理文件中的第一行,这样cmd进程就不会回显批处理文件中的每个命令。如果你的批处理文件没有为stdout或stderr生成任何其他输出,那么你就完成了。
如果批处理文件中的一个或多个命令可以生成很多stdout和/或stderr输出,那么你必须自己处理这些数据。
如果您正在使用" Runtime.getRuntime()。exec"你只有一种方法来处理这个问题,那就是通过调用来获取批处理文件的stdout和stderr的InputStream:
@echo off
现在你必须阅读每个InputStream(只有当他们有数据或你会等到你这么做)。假设您从其中一个InputStream获得的数据远多于另一个,您几乎可以确保挂起批处理文件。有一些方法可以不挂起来读取多个流,但是,它们超出了我已经过长的答案范围。
如果你正在使用 InputStream outIS = p.getInputStream (); // this gets the batch file's stdout
InputStream errIS = p.getErrorStream (); // this gets the batch file's stderr
(这是这样做的一个主要原因)你可以选择更多的选项,因为你可以要求合并stdout和stderr {{1} ,更容易处理一个InputStream而不会阻塞,或者你可以将stdout和stderr重定向到文件(null文件肯定可以在Unix上运行在Windows上)所以你编程并不需要处理它们。
不要忘记,如果你的批处理文件从stdin读取数据,你也必须处理它。 流程支持此功能, ProcessBuilder 中包含更多选项。
答案 4 :(得分:0)
如果您只是想知道批处理文件过程是否完成,为什么不添加...
echo DONE
在批处理文件的末尾?
或者,如果您的程序是供公众使用的,那就像......
echo finished>log.txt
会奏效。然后验证它是否已在java程序中完成...
if (new BufferedReader(new FileReader("log.txt")).readLine().equals("finished"))
{
System.out.println("the batch process has finished");
}