sqtd
sqtd

Reputation: 515

Execute external program

I tried to make an application that calls an external program that I have to pass two parameters. It doesn't give any errors.

The program.exe, written in C++, takes a picture and modifies the content of a .txt file.

The Java program runs but it does nothing-

Here is my sample code:

    String[] params = new String [3];
    params[0] = "C:\\Users\\user\\Desktop\\program.exe";
    params[1] = "C:\\Users\\user\\Desktop\\images.jpg";
    params[2] = "C:\\Users\\user\\Desktop\\images2.txt";
    Runtime.getRuntime().exec(params);

Upvotes: 44

Views: 170586

Answers (5)

Maj
Maj

Reputation: 27

new ProcessBuilder("command").inheritIO().start().waitFor();

explanation:

ProcessBuilder pb = new ProcessBuilder("command");

"command": like "ls"(ls command if platform supports) or "javac"(if java is installed) or "notepad" or "ping" complete path to an specific program ("path\to\autocad.exe")

Now you have a process builder ready.

Next you instruct that instead of dealing with all aspects relevant to input output programmatically, just you prefer to have the I/O in current terminal as usually you do in windows/linux terminal:

.inheritIO();

Now your process builder is even more ready.

Now you have to practically make the process via:

.start()

Now, the process is in execution, in parallel to your java program. Opposite to an ordinary way of execution of every instruction of a program that are sequentially. That means the computer won't finish that process and then go to the next instruction of your java program, and before finishing that process, further lines of code will be executed (concurrent programming, multithreading).

If you don't want that to happen, then you have to mention it via: waitFor();

Upvotes: 0

k_o_
k_o_

Reputation: 6308

This version is a Java 17 version using some built in convenience functions like the xyzReader methods and the streaming API consumption of the output. Take note that the example works for programs not running long and returning immediately when ready, so no daemons (otherwise the output processing should be done in a thread while waiting for the process to exit.).

If all the exception handling is ignored the code is really short:

        Process process = new ProcessBuilder("program", "param1", "param2").start();
        // check your program's used exit code in case or error
        if (process.waitFor() != 0) {
            throw new IOException("Program failed.");
        }
        String out;
        try (BufferedReader reader = process.inputReader()) {
            out = reader.lines().collect(Collectors.joining());
        }

A more verbose version with proper error handling:

        Process process;
        try {
            process = new ProcessBuilder("myprogram", "param1",
                    "param2").start();
            int errorCode = process.waitFor();
// adjust the error code for your use case, different programs migth not use 0 as success
            if (errorCode != 0) {
                try (BufferedReader reader = process.errorReader(StandardCharsets.UTF_8)) {
                    throw new RuntimeException(String.format("Program execution failed (code %d): %s", errorCode,
                            reader.lines().collect(Collectors.joining())));
                }
            }
        } catch (IOException e) {
            throw new RuntimeException("Could not invoke program.", e);
        } catch (InterruptedException e) {
            throw new RuntimeException("Could not wait for process exit.", e);
        }
        String output;
        try (BufferedReader reader = process.inputReader()) {
            output = reader.lines().collect(Collectors.joining());
        } catch (IOException e) {
            throw new RuntimeException("Could not invoke external program.", e);
        }

Also take into account that maybe not the inputReader is used for all output, but also the errorReader holds some information of the program output. It can also be that programs are using the inputReader for the error messages instead of the errorReader

Upvotes: 2

duffymo
duffymo

Reputation: 309018

You might also try its more modern cousin, ProcessBuilder:

Java Runtime.getRuntime().exec() alternatives

Upvotes: 17

Vishal
Vishal

Reputation: 20627

import java.io.*;

public class Code {
  public static void main(String[] args) throws Exception {
    ProcessBuilder builder = new ProcessBuilder("ls", "-ltr");
    Process process = builder.start();

    StringBuilder out = new StringBuilder();
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
        String line = null;
      while ((line = reader.readLine()) != null) {
        out.append(line);
        out.append("\n");
      }
      System.out.println(out);
    }
  }
}

Try online

Upvotes: 2

Steven
Steven

Reputation: 1375

borrowed this shamely from here

Process process = new ProcessBuilder("C:\\PathToExe\\MyExe.exe","param1","param2").start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;

System.out.printf("Output of running %s is:", Arrays.toString(args));

while ((line = br.readLine()) != null) {
  System.out.println(line);
}

More information here

Other issues on how to pass commands here and here

Upvotes: 80

Related Questions