无法从Java程序调用批处理文件

时间:2011-06-22 22:21:30

标签: java file batch-file command

我读到的所有内容都表明,在java程序中调用批处理文件的唯一方法是执行以下操作:

Process p = Runtime.getRuntime().exec("cmd /c start batch.bat");

据我所知,这创建了一个运行CMD.exe的进程,而CMD.exe又创建了一个运行批处理文件的进程。但是,CMD.exe进程在实例化批处理文件进程后似乎退出。

如何在退出CMD流程之前确认批处理文件已完成?

5 个答案:

答案 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多个字符。

解决此问题的一些方法:

  1. p.isAlive()作为批处理文件中的第一行,这样cmd进程就不会回显批处理文件中的每个命令。如果你的批处理文件没有为stdout或stderr生成任何其他输出,那么你就完成了。

  2. 如果批处理文件中的一个或多个命令可以生成很多stdout和/或stderr输出,那么你必须自己处理这些数据。

  3. 如果您正在使用" Runtime.getRuntime()。exec"你只有一种方法来处理这个问题,那就是通过调用来获取批处理文件的stdout和stderr的InputStream:

    @echo off

    现在你必须阅读每个InputStream(只有当他们有数据或你会等到你这么做)。假设您从其中一个InputStream获得的数据远多于另一个,您几乎可以确保挂起批处理文件。有一些方法可以不挂起来读取多个流,但是,它们超出了我已经过长的答案范围。

  4. 如果你正在使用 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上)所以你编程并不需要处理它们。

  5. 不要忘记,如果你的批处理文件从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");
}