I am trying to run a command from Java that will start a process that runs for several minutes. I need to just trigger the command and get the process handle and continue with other operations in a loop. At regular intervals, I will have to monitor that the process is still active.
I also need the console window to display to show the output of the process for the user.
Currently, I have tried methods from both Runtime and ProcessBuilder classes to run my command but neither of them has helped me achieve my objective.
Sample code:
//Changing the directory and running Maven exec: java command on the POM file in that directory.
String cmd = "cd C:/Test & mvn exec:java";
String finalCmd = "cmd /c \""+ cmd +"\"";
Process process = Runtime.getRuntime().exec(finalCmd);
Thread.sleep(10);
boolean alive = process.isAlive();
The value of variable alive is True, but I don't see the process got started. When the program execution is complete, only then the process starts and I am not sure why that happens.
Also to display the console window, I found from google that I need to use the below command:
String finalCmd = "cmd /c start cmd.exe /c \"" + cmd + "\"";
However, with this, the process starts immediately but I do not get the process handle as I find the alive variable shows false.
Does someone know how this objective can be achieved? I am ok if it's not possible to do both at the same time but at least I need to get the process execution to start and get the handle to monitor the process state later in my code.
Couple of things that are happening incorrectly here:
So at a minimum the following code should work:
Process process = Runtime.getRuntime().exec(new String[] {"cmd", "/c", "cd", "C:\\dev", "&&", "dir"});
int outputVal = process.waitFor();
boolean alive = process.isAlive();
System.out.format("alive %s, outputVal: %d\n",alive, outputVal);
Further suggestions:
So the code will look some thing like this:
List<String> cmdList = Arrays.asList("cmd", "/c", "cd", "C:\\dev", "&&", "dir");
ProcessBuilder pb = new ProcessBuilder(cmdList);
pb.redirectErrorStream(true); //redirect STD ERR to STD OUT
Process process = pb.start();
try (final BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line = null;
while ((line = br.readLine()) != null) {
System.out.println("std-out-line: " + line);
}
}
int outputVal = process.waitFor();
System.out.format("outputVal: %d\n", outputVal);
Since waitFor() is a blocking call, you can execute this in a separate thread or using an executorService. Sample code here:
final StringBuffer outputSb = new StringBuffer();
ExecutorService executorService = null;
try {
executorService = Executors.newSingleThreadExecutor();
final Future<Integer> future = executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
try (final BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line = null;
while ((line = br.readLine()) != null) {
outputSb.append("std-out-line: ");
outputSb.append(line);
outputSb.append('\n');
}
}
int exitValue = process.waitFor();
System.out.format("exitValue: %d\n", exitValue);
return exitValue;
}
});
while (!future.isDone()) {
System.out.println("Waiting for command to finish doing something else..");
Thread.sleep(1 * 1000);
}
int exitValue = future.get();
System.out.println("Output: " + outputSb);
} finally {
executorService.shutdown();
}
Here's a solution that uses WMIC.
public static void main( String[] args ) throws Exception {
// Vars
Process process;
String output;
// Execution
process = Runtime.getRuntime().exec("cmd /c wmic process call create calc.exe | findstr ProcessId");
output = readTrimmedOutput(process.getInputStream());
System.out.println("Output from command: " + output);
// Basic string manipulation to get process id
String str_proc_id = output.split(" = ")[1].replace(";","");
System.out.println("ProcessId is: " + str_proc_id);
// Some thread delay that you can comment/uncomment for testing if running or not
Thread.sleep(5000);
// Finding if process is still running
process = Runtime.getRuntime().exec("cmd /c wmic process get processid | findstr " + str_proc_id);
output = readTrimmedOutput(process.getInputStream());
boolean isRunning = output.contains(str_proc_id);
System.out.println("Is process still running? " + isRunning);
}
private static String readTrimmedOutput(InputStream is) throws Exception {
BufferedReader breader = new BufferedReader(new InputStreamReader(is));
String line = breader.readLine();
return line != null ? line.trim() : "";
}
Sample output
Output from command: ProcessId = 6480;
ProcessId is: 6480
Is process still running? true
For showing/displaying cmd console change some lines to:
// Execution
String your_command = "cmd.exe /c \"dir\"";
process = Runtime.getRuntime().exec("cmd /c wmic process call create \"" + your_command + "\" | findstr ProcessId");
References:
https://msdn.microsoft.com/en-us/library/aa394531(v=vs.85).aspx
https://www.computerhope.com/wmic.htm
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With