Call external exe multiple times one after another - java

I am calling an external exe using the following commands:
String bat_file = "cmd /c start out.bat";
Process p= Runtime.getRuntime().exec(bat_file);
The problem is that I need to call the specific exe multiple times but one after another(the next exe starts after the previous exe is finished). They can not run simultaneously as they access the same files.
I tried to use a for but is not working.
Any ideas?

The problem in your approach is basically the start command. It creates a separate process. If you remove it, you can successfully use waitFor:
String batchFile = "cmd /c out.bat";
Process p = Runtime.getRuntime().exec(batchFile);
int resultCode = p.waitFor();

thank you. I finally solved it using
String batchFile = "cmd /c start/wait out.bat";

Related

Java - Run a batch file and Notify when done, keeping CMD window open

I am trying to create a java program that executes a batch file and then does some code after.
My program executes the batch file perfectly but notifies me when the cmd is launched because the main thread is done.
However, I need to keep the cmd window open.
I tried using a processBuilder with .redirectErrorStream(true), but it does not display the cmd text in the window, only in the java console.
Thank you in advance for your help.
Here is my code:
String cmd = "temp.bat";
String path = "E:\\USMT\\";
Process p = Runtime.getRuntime().exec("cmd /c start " + path + cmd);
int exitVal = p.waitFor();
JOptionPane.showMessageDialog(null, "Done", "Confirmation", JOptionPane.PLAIN_MESSAGE);
Try adding pause at the end of the batch file. This should keep the cmd window from closing yet allow p.waitFor() to return.

Save output of external program call in textfile in java

I am using Windows!
I want to call a small .exe application from my java command line which is called "saucy.exe". It needs an input file "input.saucy". Both are stored in the correct directory.
When I use the command
Process p = Runtime.getRuntime().exec("saucy input.saucy");
everything works fine and I get an output on the console.
However, when I try to write the output in a file
Process p = Runtime.getRuntime().exec("saucy input.saucy > output.saucy");
nothing happens.
I already found the advice in http://www.ensta-paristech.fr/~diam/java/online/io/javazine.html and tried to tokenize the command manually:
String[] cmd = {"saucy", "input.saucy > output.saucy"};
Process p = Runtime.getRuntime().exec(cmd);
It is still not working. Any advice? It is no option for me to write the output to a file with java code, because its too slow.
Again: I am using Windows (I stress that because I read several hints for Linux systems).
> is a shell command, but you are not using one. try
String[] cmd = { "cmd", "/C", "saucy input.saucy > output.saucy" };
If you are on Java 7 you can use the new ProcessBuilder.redirectOutput mechanism:
ProcessBuilder pb = new ProcessBuilder("saucy", "input.saucy");
// send standard output to a file
pb.redirectOutput(new File("output.saucy"));
// merge standard error with standard output
pb.redirectErrorStream(true);
Process p = pb.start();
Use the getInputStream(), getOutputStream() and getErrorStream() to retrieve the output (or send input).
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Process.html

File copy using getRuntime().exec()

I am trying to copy a file. Here is the source. Note, des is string variable containing the URL.
Process process = Runtime.getRuntime().
exec("cmd.exe\t/c\tcopy\t"+source+"\t"+des);
Can anyone tell me why it does not work?
I think you should use FileUtils.copyFile() but anyways try this.
String[] command = new String[5];
command[0] = "cmd";
command[1] = "/c";
command[2] = "copy";
command[3] = "test.java";
command[4] = "D:";
Process p = Runtime.getRuntime().exec (command);
Instead of passing your command as a single string construct an array and than pass it to exec.
I tried this
String command = "cmd /c copy test.java D:";
worked fine for me.
Advice:
Use ProcessBuilder to construct the Process.
That automatically takes care of '2' - break the command into parts.
Merge the output streams (not entirely necessary, but makes it simpler to ..).
Consume (and display) the output streams.
But in general, read and implement all the recommendations of When Runtime.exec() won't.
Runtime.exec, I believe, send the string to the command processor cmd.exe. So this is running cmd.exe, running another cmd.exe inside it, and passing your arguments. I don't have a Windows machine to test it on (thank Gods) but I think there are arguments to cmd.exe to tell it to run the arguments as a command line.
Why not just use FileUtils.copyFile()?

Wait until DOS command execution has finished - Java

I am trying to import a large amount of .dmp files in a MySQL DB and since there are more than 250 files that have to be imported I wrote an app to automate the execution of the 250+ DOS commands. The code for it:
String baseCommand = "cmd /c MySQL -h localhost -u root amateurstable < ";
Process p = Runtime.getRuntime().exec(baseCommand + filePath);
It does execute the commands it is supposed to. The problem is that some of the .dmp files are larger than 100MB, but the code above does not wait until the execution of the command is finished.
When it executes the import command for a large file it does not wait until the import is over and executes the next command right after. This causes a lot of headaches in terms of responsiveness of the computer.
The question is how to make it wait until the execution of the command completes?
Runtime.exec returns a Process object that has a waitFor() method.
waitFor()
causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
Since you already have that Process object you could just add the call to waitFor()
Process p = Runtime.getRuntime().exec(baseCommand + filePath);
p.waitFor();
You could use ProcessBuilder:
ProcessBuilder pb = new ProcessBuilder(baseCommand + filePath, "");
Process start = pb.start();
start.waitFor();
use process.waitFor()
Have you looked at Apache Commons Exec as well?
http://commons.apache.org/exec/tutorial.html
Seems like you have your processing well in hand, but I think it's a little easier to work with as a wrapper over the Runtime exec. If you needed to kill a process it can make life easier.

Trouble calling batch file from Java program

Everything I read says that the only way to call a batch file from within a java program is to do something like this:
Process p = Runtime.getRuntime().exec("cmd /c start batch.bat");
From what I understand this creates a process to run CMD.exe, which in turn creates a process to run the batch file. However, the CMD.exe process appears to exit once it has instantiated the batch file process.
How can I confirm that the batch file has completed before the CMD process exits?
What jeb said, or try passing the /wait parameter to start. That should cause start to wait till the batch process completes. Try it at the command line first -- faster than rebuilding your Java app.
You could try to start the batch without the "start" command after cmd /c, as the "start.exe" creates a new process for the batch.bat.
Process p = Runtime.getRuntime().exec("cmd /c batch.bat");
This should be the correct form for you.
Process p = Runtime.getRuntime().exec("cmd /c start batch.bat");
To wait for the batch file to finish (exit) you remove the "start" after the /c.
The /c tells cmd.exe to return when cmd is finished, this you want, however, "start" means start a new cmd.exe process to execute the batch file. At this point the cmd.exe you started is finished and exits. Probably not what you want.
Either of the two code snippets below will get the batch file running and get you a Process object that you will need.
Process p = Runtime.getRuntime().exec("cmd /c batch.bat");
Or
ProcessBuilder pb= new ProcessBuilder ("cmd", "/c", "batch.bat");
Process p = pb.start ();
Now that you have a Process object you have multiple ways to wait for your batch file to finish.
The simplest way is .waitFor()
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 ();
}
You could also use waitFor(long timeout, TimeUnit unit) or p.isAlive() if they meet your needs better.
Warning If your batch is going to output a lot of data (probably more than 1024 characters, maybe less) to stdout and / or stderr your program needs to handle this data in some manner, otherwise, the pipe (s) between your program and the batch process will fill up and the batch file will hang waiting for room in the pipe to add new characters and the batch file will never return.
This is the problem that originally brought me to Stack Overflow this time. I had 17,000+ commands in a batch file and each command generated 300+ characters to stdout and any errors executing a command generated 1000+ characters.
Some of the ways to solve this:
#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.
From the output of cmd /?
/C Carries out the command specified by string and then terminates
/K Carries out the command specified by string but remains
Thus what you need is:
Process p = Runtime.getRuntime().exec("cmd /k start batch.bat");
If you want to simply find out whether the batch file process finished or not, why not add...
echo DONE
at the end of the batch file?
Or if you program is for public use, something like...
echo finished>log.txt
would work. Then verify that it is finished from within your java program...
if (new BufferedReader(new FileReader("log.txt")).readLine().equals("finished"))
{
System.out.println("the batch process has finished");
}

Categories

Resources