用Java运行bat文件并等待2

这是我的另一个问题的后续问题: 用Java运行bat文件并等待

我将此作为一个单独的问题发布的原因是我已经问过的问题得到了正确回答。 从我的一些研究中我的问题是我的案例所独有的所以我决定创建一个新问题。 请继续阅读这个问题,因为它们密切相关。

运行建议的代码会在waitFor调用时阻塞程序。 经过一些研究后,我发现waitFor方法会阻止你的进程是否有需要被处理的输出,所以你应该首先清空输出流和错误流。 我做了那些事,但我的方法仍然阻止。 然后我找到了一个简单循环的建议,在等待exitValue方法返回进程的退出值并处理抛出的exception(如果不是),暂停一小段时间以便不占用所有CPU。 我这样做了:

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(); } } } 

但我的过程不会结束! 我一直收到这个错误:

 java.lang.IllegalThreadStateException: process has not exited 

有关为什么我的流程不会退出的任何想法? 或者你有任何库建议处理正确执行批处理文件并等待执行完成?

使用/c开关而不是/k启动cmd并删除start

 Process p = Runtime.getRuntime().exec( "cmd /c SQLScriptsToRun.bat" + " -UuserName -Ppassword" + " projectName"); 

/k告诉cmd :“运行该命令然后保持打开”,而/c说“运行该命令然后退出”。

/k用于交互式使用,您需要初始化批处理文件,然后仍然使用控制台。

但是,这里的主要问题是您使用start创建了另一个进程 。 要运行批处理文件,这是完全没必要的,并且可以防止您知道批处理何时完全运行,因为Java引用了您启动的原始cmd进程,而不是您使用start生成的进程。

原则上,现在看起来如下:

  1. Java程序启动
  2. Java程序运行cmd并指示它运行start foo.bat并保持打开以进行交互式输入( /k
  3. Java记忆进程ID(PID 42)以便稍后引用该进程

    • cmd (PID 42)启动
    • cmd (PID 42)运行start foo.bat
    • start foo.bat启动另一个cmd实例,因为这是运行批处理文件时应该发生的事情
      • cmd (PID 57005)启动
      • cmd (PID 57005)运行foo.bat
      • cmd (PID 57005)退出(这标志着您想要了解的事件)
    • cmd (PID 42)显示提示并顺从地等待输入(他们不知道用户从未看过提示,也没有输入……但是cmd (PID 42)等待…)
  4. Java喜欢知道该过程是否已完成并检查PID 42

  5. 是的,它还在那里。 怎么办?

你想要什么(以及上面的改变会做什么)是:

  1. Java程序启动
  2. Java程序运行cmd并指示它运行foo.bat并在运行命令后关闭( /c
  3. Java记忆进程ID(PID 42)以便稍后引用该进程

    • cmd (PID 42)启动
    • cmd (PID 42)运行foo.bat
    • cmd (PID 42)退出
  4. Java喜欢知道该过程是否已完成并检查PID 42

  5. 万岁,流程已经消失,批处理文件已经运行。