1

I am trying to run a *.bat file (which is capable of running several commands and retrieve the output one by one) from my java application. My intention is to send one command, read output use this output for second command and again retrieve the output.

To achieve this, through Runtime.getRuntime().exec I am passing more than one command as an input to PrintWriter. Issue is that after completing all the steps only I can read the output from *.bat through buffer ,but my intention is to run one command get the output and manipulate this output to send second command.

Unfortunately is not working. Any resolution for this?..

I got the idea to send more than one command to Runtime.getRuntime().exec from this link (How to execute cmd commands via Java)

The following is the same code which I got from above link

String[] command =
    {
        "cmd",
    };
    Process p = Runtime.getRuntime().exec(command);
    new Thread(new SyncPipe(p.getErrorStream(), System.err)).start();
    new Thread(new SyncPipe(p.getInputStream(), System.out)).start();
    PrintWriter stdin = new PrintWriter(p.getOutputStream());
    stdin.println("dir c:\\ /A /Q");
    // write any other commands you want here
    stdin.close();
    int returnCode = p.waitFor();
    System.out.println("Return code = " + returnCode);
class SyncPipe implements Runnable
{
public SyncPipe(InputStream istrm, OutputStream ostrm) {
      istrm_ = istrm;
      ostrm_ = ostrm;
  }
  public void run() {
      try
      {
          final byte[] buffer = new byte[1024];
          for (int length = 0; (length = istrm_.read(buffer)) != -1; )
          {
              ostrm_.write(buffer, 0, length);
          }
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
  }
  private final OutputStream ostrm_;
  private final InputStream istrm_;
}
Community
  • 1
  • 1
Sreehari
  • 5,621
  • 2
  • 25
  • 59
  • 1
    First of all: don't use `Runtime.exec()`, use a `ProcessBuilder`. It makes redirections much easier to handle. – fge Feb 26 '14 at 11:49
  • @fge I tried with ProcessBuilder already , but couldnt achieve my requirement. Can u pls explain bit more? – Sreehari Feb 28 '14 at 07:46

3 Answers3

1

In your case I would not use Threads, you want a sequential execution path.

robermann
  • 1,722
  • 10
  • 19
  • Could you pls provide any help topics or useful links for the same , so that I can try it out and let you know the output? – Sreehari Feb 28 '14 at 07:31
  • Check this blog: http://blog.art-of-coding.eu/piping-between-processes/ . Please note that there the threads are used for moving data from a stream to another, an not in order to launch parallel tasks. If it works for you, give credit to the blogger too :) – robermann Feb 28 '14 at 08:42
1

Actually, instead of trying to reinvent the wheel, I strongly suggest you to use an expect-like java library to do that kind of thing.

Just because there are several things that you'll have to deal with, such as timeout between requests, waiting for the output to return, etc.

Take a look at these libraries

In particular, I use expectj in my project and it works pretty well (although I think expect4j is more popular)

With expectj, your code will look like this (from http://expectj.sourceforge.net/)

// Create a new ExpectJ object with a timeout of 5s
ExpectJ expectinator = new ExpectJ(5);

// Fork the process
Spawn shell = expectinator.spawn("/bin/sh");

// Talk to it
shell.send("echo Chunder\n");
shell.expect("Chunder");
shell.send("exit\n");
shell.expectClose();
Leo
  • 6,480
  • 4
  • 37
  • 52
  • Thanks for the timeliy help. In ExpectJ or Expect4J it seems to be like we should know exact output that is to be retrieved back.But in my issue again it can be any set of integer combination. Say my output can be 0102030405 or 0405060708. and from expect or through Pattern.compile I didnt found any matching logic. Am I missing something or in the wrong direction? – Sreehari Feb 28 '14 at 07:29
  • in expect4j you can expect for a regex - see this example http://nikunjp.wordpress.com/2011/07/30/remote-ssh-using-jsch-with-expect4j/ – Leo Feb 28 '14 at 12:32
0

You can do the redirection of output of one command to other in the bat file itself using pipe. I am sorry, i hadn't noticed that you want to manipulate the output first. So instead of using bat file, you can run the commands that are in bat file from java using exec , get the out put, and use the out put to execute the next command.

Smitt
  • 178
  • 7
  • To getting back the output and using the same process is not happening in Java. This is where exactly I am stuck. If i am terminating the process then I will not be able to send next command in the same session. – Sreehari Feb 28 '14 at 07:30