"Cannot run program" when using Runtime.exec with spaces in program filename
Asked Answered
G

4

2

I am using the below code to open the "sample.html' file.

String filename = "C:/sample.html";

String browser = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe";

Runtime rTime = Runtime.getRuntime();

Process pc = rTime.exec(browser + filename);

pc.waitFor();

However, I am getting the below error.

java.io.IOException: Cannot run program "C:/Program": CreateProcess error=2, The system cannot find the file specified

Could someone please help me figure this. Thanks in advance.

Gift answered 14/3, 2014 at 19:59 Comment(3)
Think about why the path is being reported incorrectly by the error message (i.e. "c:/Program" rather than "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe")Ancelin
browser + filename would be C:/Program Files (x86)/Google/Chrome/Application/chrome.exeC:/sample.html, notice any additional problems with that?Overrule
Read (and implement) all the recommendations of When Runtime.exec() won't. That might solve the problem. If not, it should provide more information as to the reason it failed. Then ignore that it refers to exec and build the Process using a ProcessBuilder. Also break a String arg into String[] args to account for arguments which themselves contain spaces.Mercedes
A
4

Runtime.exec(String) automatically splits the string at spaces, assuming the first token is the command name and the rest are command line parameters. Also you do not have a space between browser and file, although that is not the root cause of the problem.

It thinks you want to run "C:/Program" with two command line arguments:

  1. "Files"
  2. "(x86)/google/Chrome/Application/chrome.exeC:/sample.html"

Use Runtime.exec(String[]) instead, that way you have full control over what is what:

 String[] command = new String[]{browser, filename};
 Runtime.exec(command);
Arista answered 14/3, 2014 at 20:1 Comment(4)
it also need a space between browser and file, such as: exec(browser +" "+ filename);Secondary
@bluebrain Yes thank you; I didn't see file in the original version of the post. Updating now.Arista
@Bohemian No, that's not true. Runtime.exec(String,String[],File) (and therefore Runtime.exec(String) uses a StringTokenizer with default settings to split the command string into a command and parameters. Runtime.exec("a b c") attempts to run "a" with two parameters, "b" and "c".Arista
@Bohemian Jason C is correct, check this: docs.oracle.com/javase/7/docs/api/java/lang/…Secondary
A
3

Stop using Runtime.exec(String) - the problem is in how it processes the single string input.

The error message indicates how/where it is failing: note that it stops after "C:/Program" (or, the first space). This indicates that exec parsed the string "incorrectly" and thus isn't even looking for the correct executable.

Cannot run program "C:/Program"

Instead, consider the use of ProcessBuilder. While the usage is still system-dependent, ProcessBuilder allows separation of the executable file-name (and need to deal with it specially) and the arguments and does it's darnedest to invoke the target correctly.

String filename = "C:\\sample.html";
String browser = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe";

ProcessBuilder pb = new ProcessBuilder(browser, filename);
// setup other options ..
// .. and run
Process p = pb.start();
p.waitFor();

From what I can tell, in Windows, ProcessBuilder will wraps the individual components in quotes; this can create a different problem when arguments contain quotes..

Amathiste answered 14/3, 2014 at 20:14 Comment(2)
Runtime.exec(String[]) is a similar alternative but +1 (if I didn't hit my limit), ProcessBuilder is another good option. As for args containing quotes; not sure because I didn't test, but argument quotes are platform-specific so I would presume that ProcessBuilder would do the necessary escaping required for the current platform, and would therefore work correctly on arguments with quotes.Arista
@JasonC I honestly just forgot about Runtime.exec(String[]) .. :>Amathiste
C
2

Try this.

    String filename = "C:\\sample.html";
    String browser = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe";

    Runtime runtime = Runtime.getRuntime();

    try {
        runtime.exec(new String[] {browser, filename});
    } catch (IOException e) {
        e.printStackTrace();
    }
Cylindroid answered 14/3, 2014 at 20:9 Comment(1)
This does not work, as Runtime.exec(String) automatically splits the string at spaces to determine command line parameters.Arista
L
1

Parameters must be passed separately:

Process pc = rTime.exec(new String[]{browser, filename});

Using exec() is not like using the command line - you can not use spaces to delimit the command from its parameters. Your attempt would try to execute a command whose path was the concatenation of the exec and the filename as one giant string.

Loom answered 14/3, 2014 at 20:8 Comment(6)
No. There is no version of Runtime.exec that can accept two String parameters. My answer is correct. See Runtime.Arista
(As a new mod I would expect you to take extra care into researching answers, especially prior to downvoting, as your comments carry more weight than a normal user's would.)Arista
@jasonc yes there is a version (answer edited - I thought it was varargs). See Runtime.exec(String[])Loom
No. That takes (String,String[]), not (String,String), and the second parameter is the environment. See also my comments to you on my answer; both the documentation and the OP's observed error demonstrate the automatic splitting at spaces of exec(String).Arista
@JasonC yes. sorted now. I'm using my iPhone: it's a little tricky to edit/lookup etcLoom
If it's tricky then don't do it. Better to let others answer than give an incorrect answer. Please correct your answer and your comments on mine when you can. At the moment I have the only entirely correct answer here. And please do not do this again, it isn't OK. Don't make me start a flame war on meta. I didn't vote for you.Arista

© 2022 - 2024 — McMap. All rights reserved.