FULL PRODUCT VERSION :
java version "1.5.0_10"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_10-b03)
Java HotSpot(TM) Client VM (build 1.5.0_10-b03, mixed mode, sharing)
JRE 1.6.0
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
Method java.lang.Runtime.exec(String,String[],File) incorrectly handles quotes in commandline if UNC path to executable is used and it is quoted.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code and compare with Start>Run on Windows.
Start>Run can execute:
"\\slothxp\C$\Program Files\Internet Explorer\iexplore.exe" about:blank
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The process should start.
It does start correctly if I remove quotes from commandline.
ACTUAL -
Process is not created but IOException is thrown.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.io.IOException: Cannot run program ""\\host.domain.com\path\file.exe"": CreateProcess error=3, The system cannot find the path specified
at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
at java.lang.Runtime.exec(Runtime.java:593)
at java.lang.Runtime.exec(Runtime.java:431)
at java.lang.Runtime.exec(Runtime.java:328)
at com.ptc.warp.transform.Test.main(Test.java:19)
Caused by: java.io.IOException: CreateProcess error=3, The system cannot find the path specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(ProcessImpl.java:81)
at java.lang.ProcessImpl.start(ProcessImpl.java:30)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
... 4 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Test {
public static void main( String[] args ) {
try {
java.lang.Runtime.getRuntime().exec("\"\\\\slothxp\\C$\\Program Files\\Internet Explorer\\iexplore.exe\" about:blank");
} catch ( Throwable e ) {
e.printStackTrace( System.err );
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Please note that the same issue is observed in JRE 1.6.0.
Method Runtime.exec(String[],String[],File) may be used instead of Runtime.exec(String,String[],File). But in this case you should parse command line manually. I use the following code (it is experimental, I am not absolutely sure that this code is correct):
int pos = 0;
java.util.ArrayList arglist = new java.util.ArrayList();
parse_commandline: {
char c;
StringBuffer arg = new StringBuffer();
int length = startCommand.length();
do {
while ( Character.isWhitespace(startCommand.charAt(pos)) ) {
pos++;
if ( pos>=length ) break parse_commandline;
}
arg.setLength(0);
c = startCommand.charAt(pos);
if ( c=='"' ) {
pos++;
while ( pos<length && (c=startCommand.charAt(pos++))!='"' ) {
if ( c!='^' ) {
arg.append(c);
} else if ( pos<length ) {
arg.append(startCommand.charAt(pos));
} else {
arg.append('^');
break;
}
}
} else {
while ( pos<length && !Character.isWhitespace(c=startCommand.charAt(pos++)) ) {
if ( c=='^') {
if ( pos<length ) {
arg.append(startCommand.charAt(pos));
} else {
arg.append('^');
break;
}
} else if ( c=='"' ) {
pos++;
while ( pos<length && (c=startCommand.charAt(pos++))!='"' ) {
if ( c!='^' ) {
arg.append(c);
} else if ( pos<length ) {
arg.append(startCommand.charAt(pos));
} else {
arg.append('^');
break;
}
}
} else {
arg.append(c);
}
}
}
arglist.add( arg.toString() );
} while( pos<length );
} // parse_commandline
cmdarray = (String[])arglist.toArray( new String[arglist.size()] );