9

How can I make the following run?

public class ExecTest {
  public static void main(String[] args) {
    try {
      //Notice the multiple spaces in the argument
      String[] cmd = {"explorer.exe", "/select,\"C:\\New      Folder\\file.txt\""};

      //btw this works
      //String cmd = "explorer.exe /select,\"C:\\New Folder\\file.txt\"";

      //and surprisingly this doesn't work
      //String[] cmd = {"explorer.exe", "/select,\"C:\\New Folder\\file.txt\""};

      //Update: and (as crazy as it seems) the following also worked
      //String[] cmd = {"explorer.exe", "/select,\"C:\\New", "Folder\\file.txt\""};

      Runtime.getRuntime().exec(cmd);
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}

Using Java 6. Tested under Vista x64. By the way, taking the string that gets executed (you'll have to use the String version of exec to get it) and using it in the Search field of Vista's start menu will run as expected.

2
  • Is there a typo in the first case? I suspect that in second "btw" case, the /select is being treated oddly, because it's part of arg[0]. Providing a dir as an arg will open that folder. Given that they're all named the same, you could easily miss that it was one lower than you expected. I'd rename them to be different. Commented Jul 13, 2011 at 23:03
  • Well the first and second btw cases are the same commands. Here I 'm just demonstrating that the array version of exec fails in this case, while the string version worked. The path is there, and it's irrelevant i m afraid, i could have used anything.. thnx for answering Commented Jul 13, 2011 at 23:10

9 Answers 9

7

Ok, this is not simply an update but also an answer so I'm filing it as one. According to all information I could find, the following should theoretically do it:

String[] cmd = {"explorer.exe", "/select,\"C:\New", "", "", "", "", "", "", "Folder\file.txt\""};

The multiple spaces have been broken into empty strings and the array version of exec is used. Using the above array, I debugged the loop in lines 50-75 of java.lang.ProcessImpl where a string is finally constructed. The resulting string was:

explorer.exe /select,"C:\New       Folder\file.txt"

This is what is passed as the 1st argument to ProcessImpl's native create method (line 118 same class), which as it seems fails to run properly this command.

So I guess it all ends here... sadly.

Thnx prunge for pointing out the java bug. Thnx everyone for their time and interest!

Sign up to request clarification or add additional context in comments.

1 Comment

And now I'm looking for alternative ways to do this. Using jni is an option but leads to different versions of your app for 32 or 64 bit systems. Currently I'm looking into an insane solution, which in short is opening a bat file, writing the cmd in and executing the bat. Average total time is 45ms. That's excellent, the explorer.exe process takes about 500ms so this goes unnoticeable. Also this way you can exec literally everything. wdyt?
6

Always use Runtime.exec(String[]), not Runtime.exec(String) unless the command line is extremely simple.

14 Comments

I will have to disagree based on my case, since using the array version fails while the string version works. You can uncomment my code and see for yourself. I know all about the tokenizer and the problem it creates, but it doesn't help in this case. And it really is a simple command right? So my opinion would be... with Runtime.exec, use whatever you manage to get it working!!
Minos that's because you have already compensated for the parsing in the single-arg version by quoting etc. If you use the other you only have to pass the actual values, no quotes, no second-guessing required.
Don't really get it. How can this be written without escaping quotes? String[] cmd = {"explorer.exe", "/select,\"C:\\New Folder\\file.txt\""};. If you don't quote the path, and let exec do it for you then you 'll get the /select, part of the argument also quoted. Explorer will definitely not like this. Even if this is the only command with this awkwardness (not the case) this still seems buggy..when the string version works exactly as someone would expect
@Minos {"explorer.exe", "/select", "C:\\New Folder\\file.txt"}.
This will end up in the following command: explorer.exe /select "C\New Folder\file.txt". This, simply put is wrong. It is not the command I'm after. There is a space between /select and the path. Also in your example you've missed the comma after /select, but anyway the main problem is the space you introduced. Checking if explorer can handle the extra space, I see that it does, so I'll give a plus for your answer. But in general, I find it annoying that I cannot exec exactly the command I want. Why can't my string be left as is..
|
6

A miracle, it works!

Don't ask me why, but when i, after quite a while of nerve-wrecking research in the internets, was close to give up and use a temporary batch file as a workaround, i forgot to add the /select, parameter to the command, and, who would have thought, the following works on my Win 7 32Bit System.

String param = "\"C:\\Users\\ME\\AppData\\Local\\Microsoft\\Windows\\Temporary Internet Files\\\"";
try {
    String[]commands = new String[]{"explorer.exe", param};
    Process child = Runtime.getRuntime().exec(commands);
} catch (IOException e1) {
    System.out.println("...");
}

General Solution:

The solution of the bug-database mentioned by prunge in his post (https://bugs.java.com/bugdatabase/view_bug?bug_id=6511002) worked fine for me.

Reason:

Apparently the problem lies with the commenting of some characters done by java which it does before actually executing the command string. You have to do the commenting yourself by tokenizing your command string, to prevent the faulty java one to spring into action and mess everything up.

How to fix:

So, in my case i had to do the following (tokenizing my command string, so that no spaces are left inside the string):

String param[] = {
    "explorer.exe",
    "/select,C:\\Users\\ME\\AppData\\Local\\Microsoft\\Windows\\Temporary",
    "Internet",
    "Files\\"};

try {
    Process child = Runtime.getRuntime().exec(param);
} catch (IOException e1) {
    System.out.println("...");
}

As you can see i basically started a new String wherever a space occured, so "Temporary Internet Files" became "Temporary","Internet","Files".

Comments

2

Use new File(pathName).canExecute() first to check whether it's executable or not

EDIT:

public static void runAll(String... cmd)
{
    for(String s : cmd)
    {
        try
        {
            Runtime.getRuntime().exec(cmd);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

and then you can use it like: runAll("explorer.exe", "taskmgr.exe");

5 Comments

yes explorer is an executable in vista. Are you not talking about explorer? Also, please see my comments. How come the other commands work?
@Minos I don't understand your question well but see the update, is this what you're looking for?
Sorry to ask, but did you try to run my main? My question is not on how to architect this, but why that completely simple code block I posted does not run as expected. Thnx..
@Minos OK. well, maybe you have to run the program as administrator
Sure, but then why don't i need to be admin also in the non multiple spaces case? How come when there are only single spaces it works? I tried it anyway..
2

The characters ,-& and double spaces, all combined are a nightmare!

All the answers exposed here failed for "\\NAS\media\Music\Artistes\E\Earth, Wind & Fire\1992 - The eternal dance - Vol. 1 (1971-1975) (double space between 'Vol. 1' and '(1971').

I have no other choice than writing a temporary batch file:

   void openFolderOf( Album album ) {
      try {
         final String path = album._playList.getParent();
         final File batch = File.createTempFile( getClass().getSimpleName(), ".bat" );
         try( PrintStream ps = new PrintStream( batch )) {
            ps.println( "explorer.exe \"" + path + '"' );
         }
         Runtime.getRuntime().exec( batch.getAbsolutePath());
      }
      catch( final Throwable t ) {
         t.printStackTrace();
      }
   }

Note: on cmd.exe, the line explorer "\\NAS..." works well but not with Runtime.exec() nor ProcessBuilder.

1 Comment

This also was the only way that worked for me, thanks but I used buffer writer instead: File batch = File.createTempFile( "bat" + cuid, ".bat" ); BufferedWriter txt = new BufferedWriter(new FileWriter(batch.getAbsolutePath())); txt.write(winrarcmd); txt.close();
1

Could be a Java bug. See: https://bugs.java.com/bugdatabase/view_bug?bug_id=6511002

Did a bit of debugging out of curiosity, I think things are becoming unstuck in java.lang.ProcessImpl (see the constructor). Noticed that when it got to actually calling the underlying Windows API the string had turned into

explorer.exe "/select,"c:\New Folder\test.txt""

So that might explain why, as for workarounds see the bug database link.

2 Comments

That's not a bug: it is an RFE (Request for Enhancement). Specifically it is a request to document the existing behaviour.
Thank you prunge! i did some debugging as well and reached the exact same conclusion with you, the multiple spaces get trimmed (by the tokenizer on ' ' i guess) and you end up with a single space instead. No matter if you use the string or the array version of exec. A breakpoint at line 452 of the java.lang.ProcessBuilder reveals that. I will take a look at the bug you mentioned and post any findings. Thnx very very very much
0

For your specific case of needing the reveal/select command, I get around the windows quote nightmare by using cmd /c start:

String[] cmd = {"cmd", "/c", "start explorer.exe /select," + path};

Where path is the absolute path from a File object.

Comments

0

A better way to do it would be using ProcessBuilder object:

 Process p;
 p = new ProcessBuilder("/Applications/Sublime Text.app/Contents/MacOS/sublime_text", homeDir + _CURL_POST_PUT_CMDS).start();
 int exitValue = p.waitFor();
 if (exitValue != 0){
    System.out.println("Error to open " + homeDir + _CURL_POST_PUT_CMDS);
 }

Comments

-1

Simple way to resolve this problem for files is java.awt.Desktop Since 1.6 Example:

   Desktop.getDesktop().open(new File(fullFileName));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.