0

is there a limit of commands on a ProcessBuilder?

I have this array of commands:

protected String[] cmd = {
    "dism /mount-wim /wimfile:boot.wim /index:2 /mountdir:mount",
    "dism /image:mount /add-driver:\"driver\" /recurse",
    "dism /unmount-wim /mountdir:mount /commit",
    "dism /mount-wim /wimfile:install.wim /index:" + formPanel.getOsIndex() + " /mountdir:mount"
};

And this is my ProcessBuilder:

ProcessBuilder pb = new ProcessBuilder(
                "cmd.exe", "/c", cmd[0] + " && " + cmd[1] + " && " + cmd[2] + " && " + cmd[3] + " && " + cmd[1] + " && " + cmd[2]
);

But when I run it it says '&& was unexpected at this time'. When I change the processbuilder to this:

ProcessBuilder pb = new ProcessBuilder(
                "cmd.exe", "/c", cmd[0] + " && " + cmd[1] + " && " + cmd[2]
);

Then it works fine.

So my question is basically just if there's a sort of limit of how many commands a single processbuilder can pass?

Here's the whole segment of my SwingWorker method:

@Override
    protected Integer doInBackground() {

        try {
            ProcessBuilder pb = new ProcessBuilder(
                    "cmd.exe", "/c", cmd[0] + " && " + cmd[1] + " && " + cmd[2] + " && " + cmd[3] + " && " + cmd[1] + " && " + cmd[2]
            );
            pb.directory(new File(formPanel.workspaceDir.toString()));
            pb.redirectErrorStream(true);
            Process p = pb.start();
            String s;
            BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));

            while((s = stdout.readLine()) != null && !isCancelled()) {
                publish(s);
                System.err.println(s);
            }
            if(!isCancelled()) {
                status = p.waitFor();
            }
            p.getInputStream().close();
            p.getOutputStream().close();
            p.getErrorStream().close();
            p.destroy();
        } catch(IOException | InterruptedException ex) {
            ex.printStackTrace(System.err);
        }

        return status;
    }

I'm starting to wonder if there's something wrong with the actual code, not the commands.

Jonathan
  • 685
  • 1
  • 10
  • 30
  • I think the limitation is with cmd.exe – Stephen C Jan 27 '17 at 08:57
  • Im not sure why it doesn't work but I would personally create commands = new ArrayList<>(); and then pb.command(commands). And why cmd.exe in the first place? whenever you pb.start(); isn't it enough to run the commands ? also specify the working dir with pb.directory(new File(yourWorkingDir)); – LazerBanana Jan 27 '17 at 09:01
  • @Krystian_K the commands are cmd.exe specific commands – Jonathan Jan 27 '17 at 09:32
  • this might help http://stackoverflow.com/questions/10954194/start-cmd-by-using-processbuilder – LazerBanana Jan 27 '17 at 11:37

2 Answers2

3

I think the limit you have to take into account first is the limit of a command itselft (then ProcessBuilder) which is different if you're on Windows or Unix.

For Windows, according to "Command prompt (Cmd. exe) command-line string limitation" documentation :

On computers running Microsoft Windows XP or later, the maximum length of the string that you can use at the command prompt is 8191 characters. On computers running Microsoft Windows 2000 or Windows NT 4.0, the maximum length of the string that you can use at the command prompt is 2047 characters.

This limitation applies to the command line, individual environment variables (such as the PATH variable) that are inherited by other processes, and all environment variable expansions. If you use Command Prompt to run batch files, this limitation also applies to batch file processing.

For Unix, I suggest you to refer to the following Stackoverflow question which is resolved now :

Also, you should take account of limit size of an array in Java which is described into the following Stackoverflow question :

Community
  • 1
  • 1
Mickael
  • 4,458
  • 2
  • 28
  • 40
  • Not sure this is it. Starting to wonder if it's just something wrong with the whole SwingWorker code, since it did work when I didn't use SwingWorker – Jonathan Jan 27 '17 at 11:58
0

I think the whole command that you sent might be too long for cmd.exe as you use the executable there did you considered using Runtime.exec(); or something like this ?

    List<String> commands = new ArrayList<>();
    final ProcessBuilder builder = new ProcessBuilder();

    commands.add("dism /mount-wim /wimfile:boot.wim /index:2 /mountdir:mount");

And so on, additionaly im not sure if you can have whitespaces here, or you need to add everything as a seperate command.

    builder.command(commands);
    builder.directory(new File(workingDir));

    process = builder.start();
LazerBanana
  • 6,865
  • 3
  • 28
  • 47
  • That way it doesn't run it as cmd.exe though? – Jonathan Jan 27 '17 at 09:32
  • Also, does the process execute those commands in the order I added them? – Jonathan Jan 27 '17 at 09:42
  • It does run cmd yes, and it run them in the order that you add them. You may also consider waiting on the process.waitFor(); to execute one command before running another one. – LazerBanana Jan 27 '17 at 09:52
  • It doesn't run the commands through cmd for me. This is my code: http://pastebin.com/FKdLCcLi – Jonathan Jan 27 '17 at 11:09
  • try to put as a first command - "CMD" but therefore you will probably need to follow it with /c, start. I have just tried some simple code here and it works wonders. – LazerBanana Jan 27 '17 at 11:31
  • Noticed that this will basically just do the exact same like my normal string array :/ I still have to create a command for 'cmd', then a '/c' then the command, after that a '&&' etc etc. So it'll be identical to my previous one – Jonathan Jan 27 '17 at 11:52