简体   繁体   English

在Java中运行bat文件并等待2

[英]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: 原则上,现在看起来如下所示:

  1. Java program starts Java程序启动
  2. Java program runs cmd and instructs it to run start foo.bat and stay open for interactive input ( /k ) Java程序运行cmd并指示其运行start foo.bat并保持打开状态以进行交互式输入( /k
  3. 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)等待...)
  4. Java likes to know whether the process is finished and checks PID 42 Java喜欢知道该过程是否完成并检查PID 42

  5. Yup, it's still there. 是的,它仍然在那里。 Now what? 怎么办?

What you want (and what above change will do) is: 您想要的(以及上述更改将完成的工作)是:

  1. Java program starts Java程序启动
  2. Java program runs cmd and instructs it to run foo.bat and close after running the command ( /c ) Java程序运行cmd并指示其运行foo.bat并在运行命令( /c )后关闭
  3. 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)退出
  4. Java likes to know whether the process is finished and checks PID 42 Java喜欢知道该过程是否完成并检查PID 42

  5. Hooray, the process is gone, the batch file has been run. 糟糕,该过程已消失,批处理文件已运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM