38

I am writing a program in java which would execute winrar and unzip a jar file for me placed in h:\myjar.jar into the folder h:\new. My java code goes something like this

import java.io.File;
import java.io.IOException;

public class MainClass {

    public static void main(String[] args) {

        Runtime r = Runtime.getRuntime();
        Process p = null;

        try {
            File dir = new File("C:/Program Files/WinRAR");
            p = r.exec("winrar x h:\\myjar.jar *.* h:\\new", null, dir);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

When I execute this, I am getting this error

java.io.IOException: Cannot run program "winrar" (in directory "C:\Program Files\WinRAR"): CreateProcess error=2, The system cannot find the file specified
    at java.lang.ProcessBuilder.start(Unknown Source)
    at java.lang.Runtime.exec(Unknown Source)
    at java.lang.Runtime.exec(Unknown Source)
    at MainClass.main(MainClass.java:16)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
    at java.lang.ProcessImpl.create(Native Method)
    at java.lang.ProcessImpl.<init>(Unknown Source)
    at java.lang.ProcessImpl.start(Unknown Source)
    ... 4 more

Can anyone tell me why am I encountering such a problem. What is the change I need to incorporate in code so that it works?

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
Trijit
  • 501
  • 1
  • 4
  • 18

6 Answers6

51

Assuming that winrar.exe is in the PATH, then Runtime.exec is capable of finding it, if it is not, you will need to supply the fully qualified path to it, for example, assuming winrar.exe is installed in C:/Program Files/WinRAR you would need to use something like...

p=r.exec("C:/Program Files/WinRAR/winrar x h:\\myjar.jar *.* h:\\new");

Personally, I would recommend that you use ProcessBuilder as it has some additional configuration abilities amongst other things. Where possible, you should also separate your command and parameters into separate String elements, it deals with things like spaces much better then a single String variable, for example...

ProcessBuilder pb = new ProcessBuilder(
    "C:/Program Files/WinRAR/winrar",
    "x",
    "myjar.jar",
    "*.*",
    "new");
pb.directory(new File("H:/"));
pb. redirectErrorStream(true);

Process p = pb.start();

Don't forget to read the contents of the InputStream from the process, as failing to do so may stall the process

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
29

I used ProcessBuilder but had the same issue. The issue was with using command as one String line (like I would type it in cmd) instead of String array. In example from above. If I ran

ProcessBuilder pb = 
   new ProcessBuilder("C:/Program Files/WinRAR/winrar x myjar.jar *.* new");
pb.directory(new File("H:/"));
pb.redirectErrorStream(true);

Process p = pb.start();

I got an error. But if I ran

ProcessBuilder pb = 
   new ProcessBuilder("C:/Program Files/WinRAR/winrar", "x", "myjar.jar", "*.*", "new");
pb.directory(new File("H:/"));
pb.redirectErrorStream(true);

Process p = pb.start();

everything was OK.

RubioRic
  • 2,442
  • 4
  • 28
  • 35
EagleEye1984
  • 463
  • 5
  • 6
  • 1
    This fixed it for me. The critical thing was the `pb.directory(...)` statement. As others mentioned below, once you do that, you can just have the name of the exe as the first command argument. I did also have to use the cmd /c like so `List params = Arrays.asList("cmd", "/c", "quack1.exe", "inputfile.txt", "param1", "param2", "A"); ProcessBuilder pb = new ProcessBuilder(params); pb.directory(new File("C:/dev/test")); Process pr = (pb).start();` – Chris Clark May 31 '17 at 18:03
16

The dir you specified is a working directory of running process - it doesn't help to find executable. Use cmd /c winrar ... to run process looking for executable in PATH or try to use absolute path to winrar.

viator
  • 1,413
  • 3
  • 14
  • 25
  • Can u please tell me the command for knowing the absolute path..? – Trijit Oct 27 '13 at 20:05
  • p = rt.exec(new String[] {"C:\Program Files\WinRAR\winrar.exe", "x", "h:\\myjar.jar", "*.*", "h:\\new" } null, dir);...i still get the same error. – Trijit Oct 27 '13 at 20:07
  • what if you perform `rt.exec(new String[] {"cmd", "/c", "winrar.exe x h:\\myjar.jar . h:\\new"}, null, dir)` ? – viator Oct 27 '13 at 20:10
3

The complete first argument of exec is being interpreted as the executable. Use

p = rt.exec(new String[] {"winrar.exe", "x", "h:\\myjar.jar", "*.*", "h:\\new" }
            null, 
            dir);
Reimeus
  • 158,255
  • 15
  • 216
  • 276
2

My recomendation is to keep the getRuntime().exec because exec uses the ProcessBuilder.

Try

 p=r.exec(new String[] {"winrar", "x", "h:\\myjar.jar", "*.*", "h:\\new"}, null, dir);
Grim
  • 1,938
  • 10
  • 56
  • 123
0

Either way worked for me: Runtime.getRuntime().exec(...) or using the ProcessBuilder. Still for some calls it still failed with the same error as stated in the original question: "CreateProcess error=2, The system cannot find the file specified". On closer inspection, that was because I was executing a command file that made use of current directory references (%~dp0). Apparently they did not work, even when calling the command from the same directory. Using absolute paths solved the problem.

Kristiaan
  • 396
  • 3
  • 7