1

I use java to excute a command line to create a database, i get an error when i excute this piece of code:

private final String POSTGRES_PATH = "\"C:\\Program Files\\PostgreSQL\\9.3\\bin\\psql.exe\"";
private final String DATA_BASE = "bd_name";

private void creerDataBase() {
    String command = this.POSTGRES_PATH + " -U postgres -d postgres -c \"CREATE DATABASE " + this.DATA_BASE + "\"";
    System.out.println("command = " + command);
    String creerBDD = executerCommande(command);
    System.out.println("Resultat : " + creerBDD);
}

public String executerCommande(String command) {
    String line;
    String resultat = "";
    try {
        ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", command);
        builder.redirectErrorStream(true);
        Process p = builder.start();
        BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while (true) {
            line = r.readLine();
            if (line == null) {
                break;
            }
            resultat += line + "\n";
        }
    } catch (Exception e) {
        System.out.println("Exception = " + e.getMessage());
    }
    return resultat;
}

I get this result:

command = "C:\Program Files PostgreSQL\9.3\bin\psql.exe"\ -U postgres -d postgres -c "CREATE DATABASE bd_name"

and this error:

'C:\Program' n'est pas reconnu en tant que commande interne

This mean that Program is not an intern command.

but when i excute this command in CMD it work fine?

Is there any way to Build this Path because the ProcessBuilder not recognize C:\Program Files

Denys Kurochkin
  • 1,360
  • 1
  • 18
  • 34
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • it show me that the path is not recognized? – Youcef LAIDANI Aug 29 '16 at 14:50
  • 1
    Possible duplicate of [ProcessBuilder cannot run bat file with spaces in path](http://stackoverflow.com/questions/25377355/processbuilder-cannot-run-bat-file-with-spaces-in-path) – A_Di-Matteo Aug 29 '16 at 14:51
  • @A_Di-Matteo your exemple is about bat i dont need bat – Youcef LAIDANI Aug 29 '16 at 14:52
  • what did you mean @Aaron can you provide an exemple or explain it more? – Youcef LAIDANI Aug 29 '16 at 14:53
  • @YoucefLaidani the example answers your question though, check how it is solved, setting the Programs Files via the `directory` method rather than as a full path command – A_Di-Matteo Aug 29 '16 at 14:53
  • 2
    I believe you could transform your pathes to the DOS format to get rid of the spaces. Check [this SO question](http://stackoverflow.com/questions/4051088/how-to-get-dos-path-instead-of-windows-path) to learn how, and try to run the resulting path instead of the original one – Aaron Aug 29 '16 at 14:57
  • @Aaron this is work with me thank you soooooo much – Youcef LAIDANI Aug 29 '16 at 15:00

4 Answers4

2

A possible solution would be to remove the path (with spaces) from your constant field and use the directory method:

Sets this process builder's working directory. Subprocesses subsequently started by this object's start() method will use this as their working directory. The argument may be null -- this means to use the working directory of the current Java process, usually the directory named by the system property user.dir, as the working directory of the child process.

Changing your code to:

private final String POSTGRES_DIR = "C:\\Program Files\\PostgreSQL\\9.3\\bin\\"
private final String POSTGRES_COMMAND = "psql.exe";

....

ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", command).directory(new File(POSTGRES_DIR));
.....
A_Di-Matteo
  • 26,902
  • 7
  • 94
  • 128
  • Thank you @A_Di-Matteo but i think something is not clear in your code first POSTGRES_DIR not a String should be Directory and my command is **-U postgres -d postgres -c \"CREATE DATABASE " + this.DATA_BASE + "\"** so this is not clear at all for me – Youcef LAIDANI Aug 29 '16 at 15:10
  • @YoucefLaidani right, the code was just a sample to show how to restructure the existing one, not meant to be a full replacement (it is incomplete anyway). The main point was to use the `directory` method to set the current working directory: it should have solved your issue concerning the directory path with spaces. – A_Di-Matteo Aug 29 '16 at 15:13
  • thank you @A_Di-Matteo i will try it and infome you if it work thank you anyway so much – Youcef LAIDANI Aug 29 '16 at 15:14
2

Thanks for @Aaron his idea helps me so i solved this problem using this:

private final String POSTGRES_PATH = "C:\\PROGRA~1\\PostgreSQL\\9.3\\bin\\psql.exe";

this C:\\PROGRA~1 inteed of this: C:\\Program Files

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • This is a dirty warkaround, but it is a working workaround. For those who are too lazy to read the documentation :) – Denys Kurochkin Aug 29 '16 at 15:40
  • what did you mean @Denis Kurochkin ? – Youcef LAIDANI Aug 29 '16 at 18:02
  • It means that you shouldn't run one standalone program via another when you can run the first program directly. – Denys Kurochkin Aug 29 '16 at 18:21
  • With `cmd.exe` you forced to use a lot of workarounds, and that one is the only one you have found, but there are more which you don't know about. What will you do if the path is changed to another long one? Do you know how to get DOS-like path of your file? Will you add to documentation of your product instructions "how to get DOS-like path"? What will admin who is installing your app say about you if you demand him to put in configuration file DOS-like path instead of normal human-readable one? – Denys Kurochkin Aug 29 '16 at 18:25
  • Thank you @DenisKurochkin i understand now, so i will use your solution, thank you any way – Youcef LAIDANI Aug 29 '16 at 18:27
1

Don't run cmd.exe if you want to run a separate binary program.
cmd.exe is for scripts like *.cmd or *.bat

With cmd.exe you have to pass your command as an argument of CMD, and you should manage all OS-specific pitfalls like long paths with whitespaces, quotes inside qoutes etc.

Instead, you had better run psql itself.
The ProcessBuilder takes a command and all the arguments as a list of separate strings. And ProcessBuilder is clever enough to do all the necessary magic with quotes and whitespaces by itself.

And take attention to the list of arguments - shells separate arguments by whitespaces, while psql might recognize the sequence of strings as a single argument.
We may assume that -U postgress is a single argument for psql, but for shell (cmd.exe in our case) these are two separate arguments - -U and postgress, so we should pass them to the ProcessBuilder separately

So the better way to run psql is to run it directly, something like that:

 new ProcessBuilder("C:\\Program Files\\PostgreSQL\\9.3\\bin\\psql.exe", 
                    "-U", "postgres", 
                    "-d", "postgres", 
                    "-c", "\"CREATE DATABASE " + this.DATA_BASE + "\"");
Anatoly Shamov
  • 2,608
  • 1
  • 17
  • 27
Denys Kurochkin
  • 1,360
  • 1
  • 18
  • 34
0

What you could try is instead of the space between program and files is %20 or \s. So like:

command = "C:\\Program%20Files\\PostgreSQL\\9.3\\bin\\psql.exe"

or command = "C:\\Program\sFiles\\PostgreSQL\\9.3\\bin\\psql.exe"

I hope one of them works for you, please let me know

EDIT: use double \ to get it to recognize the \

Foitn
  • 604
  • 6
  • 25