ProcessBuilder adds extra quotes to command line - java

I need to build the following command using ProcessBuilder:
"C:\Program Files\USBDeview\USBDeview.exe" /enable "My USB Device"
I tried with the following code:
ArrayList<String> test = new ArrayList<String>();
test.add("\"C:\\Program Files\\USBDeview\\USBDeview.exe\"");
test.add("/enable \"My USB Device\"");
ProcessBuilder processBuilder = new ProcessBuilder(test);
processBuilder.start().waitFor();
However, this passes the following to the system (verified using Sysinternals Process Monitor)
"C:\Program Files\USBDeview\USBDeview.exe" "/enable "My USB Device""
Note the quote before /enable and the two quotes after Device. I need to get rid of those extra quotes because they make the invocation fail. Does anyone know how to do this?

Joachim is correct, but his answer is insufficient when your process expects unified arguments as below:
myProcess.exe /myParameter="my value"
As seen by stefan, ProcessBuilder will see spaces in your argument and wrap it in quotes, like this:
myProcess.exe "/myParameter="my value""
Breaking up the parameter values as Joachim recommends will result in a space between /myparameter= and "my value", which will not work for this type of parameter:
myProcess.exe /myParameter= "my value"
According to Sun, in their infinite wisdom, it is not a bug and double quotes can be escaped to achieve the desired behavior.
So to finally answer stefan's question, this is an alternative that SHOULD work, if the process you are calling does things correctly:
ArrayList<String> test = new ArrayList<String>();
test.add("\"C:\\Program Files\\USBDeview\\USBDeview.exe\"");
test.add("/enable \\\"My USB Device\\\"");
This should give you the command "C:\Program Files\USBDeview\USBDeview.exe" "/enable \"My USB Device\"", which may do the trick; YMMV.

As far as I understand, since ProcessBuilder has no idea how parameters are to be passed to the command, you'll need to pass the parameters separately to ProcessBuilder;
ArrayList<String> test = new ArrayList<String>();
test.add("\"C:\\Program Files\\USBDeview\\USBDeview.exe\"");
test.add("/enable");
test.add("\"My USB Device\"");

First, you need to split up the arguments yourself - ProcessBuilder doesn't do that for you - and second you don't need to put escaped quotes around the argument values.
ArrayList<String> test = new ArrayList<String>();
test.add("C:\\Program Files\\USBDeview\\USBDeview.exe");
test.add("/enable");
test.add("My USB Device");
The quotes are necessary on the command line in order to tell the cmd parser how to break up the words into arguments, but ProcessBuilder doesn't need them because it's already been given the arguments pre-split.

I wasn't able to get it to work in any of the above ways. I ended up writing the command to a separate script (with "\ " for each space) and writing that into a script file, then calling the script file.

Split the arguments and add it to the command list. The ProcessBuilder will append quotes to the argument if it contains space in it.
ArrayList<String> cmd= new ArrayList<String>();
cmd.add("C:\\Program Files\\USBDeview\\USBDeview.exe");
cmd.add("/enable");
cmd.add("My USB Device");

Related

Rsync using java Runtime.getRuntime().exec() with double qoute in command

Hello I am trying to execute following :
Process p = null;
StringBuffer rbCmd = new StringBuffer();
rbCmd.append("rsync -e \"ssh -i /root/.ssh/key\" -va --relative /home/lego/hyb/abc/PVR2/Testdata/./R887/SCM/System root#myMachine:/xyz/data/SCMdata/");
p = Runtime.getRuntime().exec(rbCmd.toString());
But I am getting following error on command line.Command executes correctly on command line
Missing trailing-" in remote-shell command.
rsync error: syntax or usage error (code 1) at main.c(361) [sender=3.0.6]
Issue is because of double quotes inside the command where I mention ssh key.
Please help with correction.
Your approach won't work because Runtime.exec() does not realize that "ssh -i /root/.ssh/key" is a single argument to rsync. Escaping the double-quotes keeps the compiler happy, but doesn't remove the fundamental problem, which is the limits of the built-in tokenizer.
You might have more luck with something like this:
Process p = Runtime.getRuntime().exec
(new String[]{"rsync", "-e", "ssh -i /root/.ssh/key", "-va" "--relative" ... });
That is, tokenize the command line yourself, and form the individual tokens into a String[]. You're deciding in advance what the arguments to rsync are, rather than allowing exec() to figure it out (wrongly).
Don't forget that if rsync produces any output, you'll need to arrange for your application to consume its stdout and stderr, or it could stall.

Run external app by userinput

So I'm creating a Java program and I want to make it so that you can ask it to open a program.
But, here's the catch, I want the program it opens to be taken from the user input, right now I'm trying to change this
try{Process p = Runtime.getRuntime().exec("notepad.exe");}
catch(Exception e1){}
Into something that opens a program that you asked it to open.
Here's an example of what I want:
User: Can you open chrome?
Program: Of course, here you go!
chrome opens
Could anyone tell me how I would be able to do this?
You can do it in two ways:
1.By Using Runtime:
Runtime.getRuntime().exec(...)
So, for example, on Windows,
Runtime.getRuntime().exec("C:\application.exe -arg1 -arg2");
2.By Using ProcessBuilder:
ProcessBuilder b = new ProcessBuilder("C:\application.exe", "-arg1", "-arg2");
or alternatively
List<String> params = java.util.Arrays.asList("C:\application.exe", "-arg1", "-arg2");
ProcessBuilder b = new ProcessBuilder(params);
or
ProcessBuilder b = new ProcessBuilder("C:\application.exe -arg1 -arg2");
The difference between the two is :
Runtime.getRuntime().exec(...)
takes a single string and passes it directly to a shell or cmd.exe process. The ProcessBuilder constructors, on the other hand, take a varargs array of strings or a List of strings, where each string in the array or list is assumed to be an individual argument.
So,Runtime.getRuntime.exec() will pass the line C:\application.exe -arg1 -arg2 to cmd.exe, which runs a application.exe program with the two given arguments. However, ProcessBuilder method will fail, unless there happens to be a program whose name is application.exe -arg1 -arg2 in C:.
You can try it with like. Pass whole path of where you install chrome.
try{
Process p = Runtime.getRuntime().exec("C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe");
}
catch(Exception e1){
}
When using exec, it is essentially the same as if you were using the command line on windows. Open Command Prompt, type open, and see if it gives details as to how it opens files. If not, find the opener. Usually when dealing with command line operations, there are multiple parameters that are required for opening files/applications. An example of this would be for opening the "TextEdit.app" application on a mac.
Process p = Runtime.getRuntime().exec("open -a TextEdit.app");
Terminal(for mac) would open the app using the -a flag, meaning "application." You could open a file doing:
Process p = Runtime.getRuntime().exec("open filename.file_ext -a TextEdit.app");
The second one will tell the computer to find the application named <app_name>.app and open the file filename.file_ext
I know this is not going to work for a windows machine, but it's only to show how to use the command line operations for opening files and applications. It should be similar for windows though.
Hope this helps

How to change the System clock of a Linux machine by using Java?

I know that by using the command in the terminal
date --set="2011-12-07 01:20:15.962"
you would actually be able to change the System clock, so I tried it in Java and came up with the following statement
Process p = Runtime.getRuntime().exec("date --set=\"2011-12-07 01:20:15.962\"");
but it was not able to set the clock.
Do you have any idea guys how it may be able work?
Premise:
The machine is Slackware,
The privilege is root level
There are two problems with this line of code:
Process p = Runtime.getRuntime().exec("date --set=\"2011-12-07 01:20:15.962\"");
You did not wait for the process to complete (see also http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html#waitFor())
Parameters should be separated from program name, try this:
"date", "-s", "2011-12-07 01:20:15.962"
Alternatively, invoke shell as the process, and pass in a line of code:
.exec("sh", "-c", "date --set=\"2011-12-07 01:20:15.962\"")
Process p=Runtime.getRuntime().exec(new String[]{"date","--set","2011-12-07 01:20:15.962"});
The above statement worked like magic. #Howard Gou was right with "Parameters should be separated from program name"
The parts of the command statement should be passed by using a String array.

Using quotes and double quotes in Java Runtime.getRuntime().exec(...)

I am trying to start a Lisp Image from Java in Mac OSX. Using the Image from my console I type the following:
lisp_image --eval '(package::method "some_argument")'
everything runs fine.
In Java I have the problem to pass the quotes and double quotes using the Runtime.getRuntime().exec("lisp_image --eval '(package::method \"some_argument\")'").
I also tried to use :
Runtime.getRuntime().exec(new String[] {"lisp_image", "--eval ", "\'(package::method ",
"--eval ", "\"", "some_argument", "\")", "\'"});
and various things with escaping using the backslash. Nothing works.... Using String Array seems to work only for Unix (or Windows) commands.
Any ideas?
Thanks in advance,
Sven
As I understand it you want to invoke the list_image with two arguments, --eval and '(package::method \"some_argument\")' where the single quotes is just there to prevent the shell from breaking it up into multiple arguments.
Then you should use
Runtime.getRuntime().exec(new String[] {"lisp_image", "--eval", "(package::method \"some_argument\")"});

Passing arguments form java program to bash script that call another java programa with the arguments

I want to executing a shell scripting in my java program passing a argument showed bellow:
Runtime.getRuntime().exec("./test.sh " + "\\\"param1\\\"\\\"param2\\\"\\\"param3\\\"");
And the test.sh will call another java program passing the string argument like this:
another.jar \"param1\"\"param2\"\"param3\"
and finally the program anther.jar will interpret the argument in this format
another.jar "param1""param2""param3"
I'm a bit confuse with this bacause I can't deal correctly with escapes characters in this situation..kkk
I tried some strings formats in the first command but I didn't get the correct form.
Some help will be fine!
Thx!
Use ProcessBuilder. Nothing special needs to be done with the parameters, they'll just trickle through.
//ProcessBuilder pb = new ProcessBuilder("test.sh", "param1", "param2", "param3");
ProcessBuilder pb = new ProcessBuilder("test.sh", "param1 " + "param2 " + "param3");
pb.start();
In test.sh:
java -jar program2 $1 # Or however you want to call it.
In program2.java
public static void main(String[] args)
{
System.out.println(args[0]);
}
I think you would be better off using exec(String[] cmdarray) instead of exec(String cmd). This is because exec(String cmd) tokenizes the arguments via StringTokenizer, which pays no attention at all to double quotes when breaking up the command line arguments.
Try something like this:
ArrayList<String> argList = new ArrayList<String>();
argList.add("param1");
argList.add("param2");
argList.add("param2");
String[] args = argList.toArray(new String[argList.size()]);
Runtime.getRuntime().exec("mycommand", args);
Characters inside the param values should not need quoting or escaping, except insofar as Java source code string literals may require escaping.

Categories

Resources