I'm trying to use ProcessBuilder to start application in cmd.exe, wait for it to finish and then close it. So far I tried:
String[] cmdline=new Stirng{}("cmd.exe","/C","start",application_and_parameters);
ProcessBuilder processBuilder = new ProcessBuilder(cmdline);
Process p = processBuilder.start();
//get error and input streams
int exitVal = p.waitFor();
It opens window as expected, but doesn't close. I tried:
p.destroy()
and to send exit command:
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
writer.write("exit");
writer.flush();
but without success, cmd stays. Could anyone suggest a solution?
Remove start , It will execute your process directly without opening command prompt so you will not need to close it manually.Below is you code snippet as an example
String[] cmdline=new String[]{"cmd.exe","/C","notepad.exe"};
ProcessBuilder processBuilder = new ProcessBuilder(cmdline);
Process p = processBuilder.start();
//get error and input streams
int exitVal = p.waitFor();
System.out.println(exitVal);
Related
I want to run a exe program from my Java application.I try this code for it.
I run the batch file and batch file runs the exe.
try {
String command = "C:\\tryfile\\Runprogram.bat";
// ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command);
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process p = pb.start();
InputStream is = p.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
int excode = p.waitFor();
System.out.println(excode + " asfasf");
p.destroy();
} catch (Exception e) {
e.printStackTrace();
}
The exe runs well and does what I want.(It insert from csv file to database with bcp).There is no problem about it.
But waitfor method returns 2147483647.
What is it?I have no idea about it.I know that if the exe run and finish without any error it returns 0 normally.But my exe returns 2147483647.
Any idea?
My bat file is here:
C:\tryfile\myprogram.exe
You are getting the exit code of the BAT, not the return code of the EXE. But you have not specified an exit code in your BAT so you get trash.
I don't have a windows box on hand but something like this should work
C:\tryfile\myprogram.exe
EXIT /B %ERRORLEVEL%
Check Batch files - Errorlevels
With this, we can execute "build in" commands in java. However if we want to run some custom commands from this, Changing "pwd" to "device_id -l" doesn't work. "device_id -l" should list all the ids of attached devices of currently host. if "device_id -l" is executed in terminal itself. it works fine. There is not a question for the "build in" bash commands. Thank you.
String cmd = "pwd";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
pr.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
while ((line=buf.readLine())!=null)
System.out.println(line);
We can excuate
You can try using ProcessBuilder.
// create process
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "device_id", "-l");
// start process
Process p = pb.start();
// wait for process exit
p.waitFor();
// read process output
BufferedReader buf = new BufferedReader(newInputStreamReader(p.getInputStream()));
String line = "";
while ((line=buf.readLine())!=null)
System.out.println(line);
You need to split your command+arguments to a String array. In your case, if you want to execute "device_id -l", split that into an array like this:
String[] cmd = new String[] {"/full/path/to/device_id", "-l"};
Process pr = Runtime.getRuntime().exec(cmd);
And, you might want to use ProcessBuilder.
String[] cmd = new String[] {"/full/path/to/device_id", "-l"};
ProcessBuilder pb = new ProcessBuilder(cmd);
Process pr = pb.start();
Finally, you'll have to take into account that Java does not look for executables in PATH (like command shell does), you'll have to provide full path to the executable/script that you want to execute (or it has to be in the working directory; you can set the working directory with ProcessBuilder.directory(File)).
See also: Difference between ProcessBuilder and Runtime.exec()
How can I give multiple command in process builder.
Basically my first command is to enter in nusmv interface then further commands are nusmv commands to create xml file but my program is not working after first command, it is not taking further commands.
String[][] commands = {
{"nusmv", "-int", "D:/files/bitshift.smv"},
{"go"},
{"process_model"},
{"show_traces","-p","4","-o","D:output.xml"}};
for (String[] str : commands) {
ProcessBuilder pb = new ProcessBuilder(str);
pb.redirectErrorStream(true);
Process process = pb.start();
InputStream is = process.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
System.out.println(inputLine);
}
System.err.println("next one");
}
You need to brush up your understanding of the process model, and read the ProcessBuilder documentation in light of that.
What your code does is, create a process to run the command "nusmv -int D:/files/bitshift.smv", then create a new process to (try to) run the command "go", and so on. Clearly that is not what you want.
You want one process; you want it to run "nusmv", and you want to write commands to its input. Assuming that "nusmv" reads commands from stdin in a conventional way, you should be able to do something like:
ProcessBuilder pb = new ProcessBuilder("numv","-int","D:/files/bitshift.smv");
Process process = pb.start();
// Write commands
PrintWriter commands = new PrintWriter(process.getOutputStream());
commands.println("go");
commands.println("processmodel");
commands.println("show_traces -p 4 -o D:output.xml");
commands.close();
// Read from process.getInputStream(), process.waitFor(), process.exitValue()
...
I'm trying to run a Java application which creates a new powershell process on startup and then later on interacts with it multiple times. Calling powershell.exe and have it execute a single command and return the output works fine for me. The problem arises if I don't want the powershell process to immediately finish/exit but to stay open so I can write to its outputStream and receive results back from the inputStream.
String input = "dir";
String[] commandList = {"powershell.exe", "-Command", "dir"};
ProcessBuilder pb = new ProcessBuilder(commandList);
Process p = pb.start();
if(input != null) {
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(p.getOutputStream())), true);
writer.println(input);
writer.flush();
writer.close();
}
//p.getOutputStream().close();
Gobbler outGobbler = new Gobbler(p.getInputStream());
Gobbler errGobbler = new Gobbler(p.getErrorStream());
Thread outThread = new Thread(outGobbler);
Thread errThread = new Thread(errGobbler);
outThread.start();
errThread.start();
System.out.println("Waiting for the Gobbler threads to join...");
outThread.join();
errThread.join();
System.out.println("Waiting for the process to exit...");
int exitVal = p.waitFor();
System.out.println("\n****************************");
System.out.println("Command: " + "cmd.exe /c dir");
System.out.println("Exit Value = " + exitVal);
List<String> output = outGobbler.getOuput();
input = "";
for(String o: output) {
input += o;
}
System.out.println("Final Output:");
System.out.println(input);
This code returns the result of the "dir" command from a powershell - fine. But as you can see, I'm trying to run a second "dir" command using
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(p.getOutputStream())), true);
writer.println(input);
writer.flush();
This has no effect whatsoever - no second dir output is shown when I run my code. I've also experimented with a powershell.exe option to open the powershell but not close it immediately:
String[] commandList = {"powershell.exe", "-NoExit", "-Command", "dir"};
But then my code hangs, meaning the Gobbler's who consume the process's inputStream don't read anything - strangely enough: they don't even read the first line - there must be at least some output....
I've also tried to close the process's outputStream after writing the second "dir" command to it - didn't change anything.
Any help is highly appreciated.
Thanks
Kurt
This sounds about right for the nature of a process spun up by another process. I think you're experiencing pretty standard behavior.
This is the key: p.waitFor()
From Java docs:
causes the current thread to wait, if necessary, until the process represented by this Process object has terminated.
You won't be able to receive the PowerShell output stream until it has terminated. When you run with -NoExit it never exits which is why you are experiencing the hang.
If you run ProcExp from Sysinternals you'll be able to see your Java process spin up an child PowerShell process.
So I don't think you'll be able to interact with it like it's a live object in memory.
I have a Java application which for example needs to restart itself (but also needs to start other processes). This is currently done by closing the current application and then start a new instance using a ShutdownHook and a ProcessBuilder.
My problem is now that the new process runs somewhere in the background and does not have its own console window. On windows machines, a new console window can be created using
cmd /c start "windowtitle" java -jar myApp.jar
But this creates 2 processes: the cmd process and the java process started by 'start'. This makes it for example impossible to get the stdout and stderr of the started process, because we only get those streams for the cmd process, not for the one started by the 'start' command.
The very best solution for me would be to reuse the current console window for the new process but this seems somehow impossible to achieve as i did not find any information on how to do this.
Additionally I would appreciate a solution which works on Unix machines.
Seems, you owe to use small console program-starter for java. It must start java and immediately exit.
#include <windows.h>
#include <tchar.h>
int main(int argc, char** argv)
{
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi = {};
CreateProcess(NULL,_T("java -jar myApp.jar"),0,0,0,NORMAL_PRIORITY_CLASS,0,0,&si,&pi);
return 0;
}
I do not know if that's what you're looking for, but it might help.
List<String> command = Arrays.asList("java", "-jar", "myApp.jar");
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process process = builder.start();
InputStream is = process.getInputStream();
final InputStreamReader isr = new InputStreamReader(is);
final BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.getLine()) != null) {
System.out.println("child process: " + line);
}
process.waitFor();
The builder.redirectErrorStream(true); will redirect the stderr to stdout and the while loop will write the stdout of the child process to the stdout of your main application. And don't forget to try catch the Streams and Buffers