[英]Run bat file in Java and wait 2
This is a followup question to my other question : Run bat file in Java and wait 这是我另一个问题的跟进问题: 在Java中运行bat文件并等待
The reason i am posting this as a separate question is that the one i already asked was answered correctly. 我将其作为一个单独的问题发布的原因是,我已经问过的问题得到了正确回答。 From some research i did my problem is unique to my case so i decided to create a new question.
通过一些研究,我发现我的问题是我所遇到的问题所独有的,因此我决定创建一个新问题。 Please go read that question before continuing with this one as they are closely related.
由于它们关系密切,因此请先阅读该问题,然后再继续进行此问题。
Running the proposed code blocks the program at the waitFor invocation. 运行建议的代码会在waitFor调用时阻止程序。 After some research i found that the waitFor method blocks if your process has output that needs to be proccessed so you should first empty the output stream and the error stream.
经过一番研究,我发现,如果您的进程具有需要处理的输出,则waitFor方法会阻塞,因此您应该首先清空输出流和错误流。 I did those things but my method still blocks.
我做了这些事情,但我的方法仍然受阻。 I then found a suggestion to simply loop while waiting the exitValue method to return the exit value of the process and handle the exception thrown if it is not, pausing for a brief moment as well so as not to consume all the CPU.
然后,我发现一个建议,可以在等待exitValue方法返回过程的退出值时简单地循环并处理抛出的异常(如果不是),暂停一会儿,以免消耗掉所有CPU。 I did this:
我这样做:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) {
try {
Process p = Runtime.getRuntime().exec(
"cmd /k start SQLScriptsToRun.bat" + " -UuserName -Ppassword"
+ " projectName");
final BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
final BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
new Thread(new Runnable() {
@Override
public void run() {
try {
while (input.readLine()!=null) {}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
while (error.readLine()!=null) {}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
int i = 0;
boolean finished = false;
while (!finished) {
try {
i = p.exitValue();
finished = true;
} catch (IllegalThreadStateException e) {
e.printStackTrace();
try {
Thread.sleep(500);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
System.out.println(i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
but my process will not end! 但是我的过程不会结束! I keep getting this error:
我不断收到此错误:
java.lang.IllegalThreadStateException: process has not exited
Any ideas as to why my process will not exit? 关于为什么我的流程无法退出的任何想法? Or do you have any libraries to suggest that handle executing batch files properly and wait until the execution is finished?
还是您有任何库建议使用适当的批处理文件,然后等待执行完成?
Start cmd
with the /c
switch instead of /k
and get rid of the start
: 使用
/c
开关而不是/k
来启动cmd
并摆脱start
:
Process p = Runtime.getRuntime().exec(
"cmd /c SQLScriptsToRun.bat" + " -UuserName -Ppassword"
+ " projectName");
/k
tells cmd
: “Run that command and then stay open”, while /c
says “Run that command and then exit.” /k
告诉cmd
:“运行该命令,然后保持打开状态”, /c
则显示“运行该命令,然后退出”。
/k
is for interactive use where you want an initializing batch file and afterwards still use the console. /k
供交互式使用,您需要初始化批处理文件,然后仍使用控制台。
Your main problem here, however, is that you are creating yet another process by using start
. 但是,这里的主要问题是您正在使用
start
创建另一个进程 。 To run a batch file this is totally unnecessary and prevents you from knowing when the batch was run completely, since Java has a reference to the original cmd
process you started, not the one you spawned with start
. 要运行批处理文件,这是完全没有必要的,并且可以防止您知道批处理何时完全运行,因为Java引用了您启动的原始
cmd
进程,而不是您使用start
生成的cmd
进程。
In principle, this now looks like the following: 原则上,现在看起来如下所示:
cmd
and instructs it to run start foo.bat
and stay open for interactive input ( /k
) cmd
并指示其运行start foo.bat
并保持打开状态以进行交互式输入( /k
) Java memorizes the process ID (PID 42) to later reference that process Java存储进程ID(PID 42),以便以后引用该进程
cmd
(PID 42) starts cmd
(PID 42)启动 cmd
(PID 42) runs start foo.bat
cmd
(PID 42)运行start foo.bat
start foo.bat
launches another instance of cmd
, since that's what should happen to run batch files start foo.bat
启动cmd
另一个实例,因为这是运行批处理文件时应执行的操作
cmd
(PID 57005) starts cmd
(PID 57005)启动 cmd
(PID 57005) runs foo.bat
cmd
(PID 57005)运行foo.bat
cmd
(PID 57005) exits (This marks the event you'd like to know about) cmd
(PID 57005)退出(这表示您想了解的事件) cmd
(PID 42) shows the prompt and obediently waits for input (unbeknownst to them the prompt is never seen by a user and no input will ever come ... but cmd
(PID 42) waits ...) cmd
(PID 42)显示提示并听从等待输入(对于他们而言,未知的提示是用户从未看到过提示,并且永远不会输入...但是cmd
(PID 42)等待...) Java likes to know whether the process is finished and checks PID 42 Java喜欢知道该过程是否完成并检查PID 42
What you want (and what above change will do) is: 您想要的(以及上述更改将完成的工作)是:
cmd
and instructs it to run foo.bat
and close after running the command ( /c
) cmd
并指示其运行foo.bat
并在运行命令( /c
)后关闭 Java memorizes the process ID (PID 42) to later reference that process Java存储进程ID(PID 42),以便以后引用该进程
cmd
(PID 42) starts cmd
(PID 42)启动 cmd
(PID 42) runs foo.bat
cmd
(PID 42)运行foo.bat
cmd
(PID 42) exits cmd
(PID 42)退出 Java likes to know whether the process is finished and checks PID 42 Java喜欢知道该过程是否完成并检查PID 42
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.