我读到的所有资料都说,从Java程序中调用批处理文件的唯一方法是像这样做:
Process p = Runtime.getRuntime().exec("cmd /c start batch.bat");
据我所知,这将创建一个进程来运行CMD.exe,然后创建一个进程来运行批处理文件。但是,一旦实例化了批处理文件进程,CMD.exe进程似乎就会退出。
如何确认批处理文件在CMD进程退出之前已完成?
我读到的所有资料都说,从Java程序中调用批处理文件的唯一方法是像这样做:
Process p = Runtime.getRuntime().exec("cmd /c start batch.bat");
据我所知,这将创建一个进程来运行CMD.exe,然后创建一个进程来运行批处理文件。但是,一旦实例化了批处理文件进程,CMD.exe进程似乎就会退出。
如何确认批处理文件在CMD进程退出之前已完成?
Process p = Runtime.getRuntime().exec("cmd /c batch.bat");
如果你想等待批处理文件执行完毕后再进行下一步操作,需要将命令中的 "start" 去掉。"/c" 告诉 cmd.exe 在命令完成后返回,这是你想要的,但是 "start" 意味着启动一个新的 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 ();
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()
,如果它们更符合你的需求的话。@echo off
as the 1st line in the batch file, with this the cmd process will not echo each command in the batch file. If your batch file does not generate any other output to stdout or stderr you are done.
If one or more of the commands in the batch file can or may generate a lot of stdout and / or stderr output then you have to handle that data yourself.
If you are using "Runtime.getRuntime().exec" you only have one way to handle this and that is to get the InputStreams for the batch file's stdout and stderr by calling:
InputStream outIS = p.getInputStream (); // this gets the batch file's stdout
InputStream errIS = p.getErrorStream (); // this gets the batch file's stderr
Now you have to read each of the InputStreams (only when they have data or you will wait until you do). Assuming that you get a lot more data from one of the InputStreams than the other you are almost assured of hanging the batch file. There are ways to read multiple streams without hanging, however, they are beyond the scope of my already excessively long answer.
If you are using ProcessBuilder pb= new ProcessBuilder ("cmd", "/c", "batch.bat");
(and this is a major reason to do so) you have a lot more options available to you since you can ask for stdout and stderr to be combined pb.redirectErrorStream (true);
, easier to handle one InputStream without blocking, or you can redirect stdout and stderr to files (null files may work on Windows definitely on Unix) so you program doesn't have to handle them.
Don't forget that if your batch file reads data from stdin, you have to handle that as well. This is supported in Process and with more options in ProcessBuilder.
您可以尝试在cmd /c之后不使用“start”命令来启动批处理,因为“start.exe”会为batch.bat创建一个新进程。
Process p = Runtime.getRuntime().exec("cmd /c batch.bat");
p.waitFor();
。 - aalkucmd /c start /wait cmd /c batch.bat
。我成功地运行了这个测试 Process p = Runtime.getRuntime().exec("cmd /c start /wait cmd /c \"c:\\batch.bat > %temp%\\out\""); p.waitFor();
。 - aalku根据jeb所说,或者尝试传递/wait
参数给start
。这将导致start
等待批处理过程完成。首先在命令行中尝试使用它-比重新构建Java应用程序更快。
start /wait
应该能够工作,但是使用 /wait
开关会使得启动变得完全没有必要。 - jeb从 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");
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");
}
ProcessBuilder
而不是Runtime.getRuntime().exe()
。 - OscarRyz