Search code examples
javajavafxprocessbuilder

Starting external application inside Java


I'm having trouble starting an application from my JavaFX GUI. I'm using ProcessBuilder. It creates the process, but the application won't launch until I close my Java program. Is it because that specific program is waiting for arguments or something wrong with my code?

@FXML
private void runWorldpac() {
    try {
        ProcessBuilder process = new ProcessBuilder("C:\\speedDIAL\\speedDIAL.exe");
        Process p = process.start();

    } catch (IOException e) {
        e.printStackTrace();
    }

}

External application starts but won't allow any interaction with the original application until i close this external program. Tried running a new thread, same result. Here's the new code:

try {
            ProcessBuilder process = new ProcessBuilder("C:\\speedDIAL\\speedDIAL.exe");
            Map<String, String> environ = process.environment();
            Process p = process.start();
            InputStream is = p.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line;
            while ((line = br.readLine()) != null) {
                //System.out.println(line);
            }
            System.out.println("Program terminated!");
        } catch (IOException e) {
            e.printStackTrace();
        }

Solution

  • Read that article, good info. Also read another good example on here. It's running in a new thread now, but my program is waiting for the external application to finish before it continues, I understand that's usually desired, but not in this case, how can i disable that?

    Wait for the production of the exit value in a new thread. Something like:

    try {
        ProcessBuilder pBuilder = new ProcessBuilder("C:\\speedDIAL\\speedDIAL.exe");
    
        // don't forget to handle the error stream, and so 
        // either combine error stream with input stream, as shown here
        // or gobble it separately
        pBuilder.redirectErrorStream(true); 
        final Process process = pBuilder.start();
        final InputStream is = process.getInputStream();
    
        // in case you need to send information back to the process
        // get its output stream. Don't forget to close when through with it
        final OutputStream os = process.getOutputStream();
    
        // thread to handle or gobble text sent from input stream 
        new Thread(() -> {
            // try with resources
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(is));) {
                String line = null;
                while ((line = reader.readLine()) != null) {
                    // TODO: handle line
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }).start();
    
        // thread to get exit value from process without blocking 
        Thread waitForThread = new Thread(() -> {
            try {
                int exitValue = process.waitFor();
                // TODO: handle exit value here
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        waitForThread.start();
    
        // if you want to join after a certain time:
        long timeOut = 4000;
        waitForThread.join(timeOut);
    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }