13

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?

oberlies
  • 11,503
  • 4
  • 63
  • 110
stefan.at.kotlin
  • 15,347
  • 38
  • 147
  • 270
  • Nice observation! Is there any document which describes that ProcessBuilder quotes every argument with double quotes? – petertc Feb 26 '14 at 12:24

5 Answers5

18

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.

KJP
  • 519
  • 5
  • 10
  • 2
    have you ever found an official reference that states ProcessBuilder will "see spaces in your argument and wrap it with quotes"? I can confirm that from my testing, but, it's crazy that no JavaDoc ever states that (or at least none that I could find). Nice answer! – mateuscb Jan 25 '17 at 15:50
10

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\"");
Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • Thank you Joachim, you are right. The reason I am getting additional quotes is the space between enable and "my...". Splitting it like you suppose works. As I read a full command from an XML file, parsing now gets a little bit more complicated, but that's another story ;-) – stefan.at.kotlin Aug 25 '12 at 19:27
5

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.

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
0

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.

Laine Mikael
  • 173
  • 2
  • 6
0

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");   
Dan
  • 11
  • 3