Ejecutar un .exe y esperar a que termine

Buenos días:
Quisiera saber si alguien puede ayudarme para la solución de este problema:
Tengo una aplicación de java que al arrancar tiene que lanzar una aplicación externa, (un .exe que procesa un archivo y crea un archivo de salida para después manipular dicha salida en la aplicación java), y lo que quiero saber básicamente es el modo correcto de invocarlo, esperar a que termine su ejecución.

Lo que he hecho es esto:

public static void main(String[] args) {

System.out.println("Carga Full v1");
fecha=Calendar.getInstance();

System.out.println(fecha.getTime()+": Ejecutando programa.exe");
try{

if(java.awt.Desktop.isDesktopSupported()){
try{
System.out.println(fecha.getTime()+": Abriendo programa.exe.");
Desktop dk = Desktop.getDesktop();
File ffiltroa =new File("programa.exe");
dk.open(ffiltroa);

System.out.println(fecha.getTime()+": Finalizado programa.exe");
}catch(Exception e){
System.out.println("Error al abrir programa: "+e.getMessage());
}
}
catch(Exception e){
System.out.println("Error al abrir programa: "+e.getMessage());
}

/* llamar a los demas metodos del programa, donde proceso el archivo generado por 'programa.exe', solo tengo que insertar en una base de datos y luego abrir una url, esta parte ya la hace bien */
}

El problema es que realmente no se ejecuta 'programa.exe' y en caso de que lo abra, no espera a que termine y se sigue con lo demas...alguien podria ayudarme a saber como ejecutar ese comando y esperar a que termine su ejecución para seguir con lo demás? de antemano agradezco la ayuda. Ya investigué acerca del uso de Runtime.getRuntime() y Process, pero tampoco me ha funcionado.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de rugi

Te debe de interesar este

Te debe de interesar este artículo:
Ademas del Runtime. ahora ya tenemos dispobible la clase ProcessBuilder.

http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-pro...

Saludos!!
---

Process  process = new

Process  process = new ProcessBuilder("some.exe", "param", param).start().waitFor();
System.out.println();  

Ejemplo práctico:

$cat Lp.sh
echo Empieza
echo Espera
sleep 10
echo Termina

$./Lp.sh
Empieza
Espera
Termina
$
$cat Ya.java
class Ya {
    public static void main( String ... args ) throws java.io.IOException , InterruptedException {
        System.out.println(" Este es Java ");
        new ProcessBuilder("./Lp.sh" ).start().waitFor();
        System.out.println(" Da daaaa" );
    }
}
$javac Ya.java
$java Ya
 Este es Java
 Da daaaa

Como ves es muy fácil. Me parece que el programa Lp.sh debería correr exactamente igual en Windows con solo salvarlo con extensión .cmd

Ahora.. si necesitas leer la salida generada por ese programa, hay que pedirle al objeto process, el input stream para luego...

Mejor lo digo con código:

$cat Ya.java
import java.io.InputStream;
import java.util.Scanner;
class Ya {
    public static void main( String ... args ) throws java.io.IOException , InterruptedException {
        Process p = new ProcessBuilder("./Lp.sh" ).start();
        InputStream input = p.getInputStream();
        p.waitFor();
        System.out.println( "El resultado fue: "+ new Scanner( input ).useDelimiter("\\A").next() );
    }
}
$
$
$javac Ya.java

$
$
$java Ya
El resultado fue: Empieza
Espera
Termina

Y listo. Hay que leer muy bien la documentación ( http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ) para saber como usar la clase apropiadamente. Es probable que necesites cerrar el inputStream después de leerlo, o que el process necesite algún cuidado extra. También la forma de leer no necesariamente la querras en un string o la puedes leer de otra forma

Espero que esto te sirva.

P.D. La razón por la cual no ejecuta tu programa es porque no lo conoce. Por ejemplo abre una consola y escribe en la lista de comandos: "ayayya.exe" ( no va a hacer nada ) ... te va a decir que no existe el archivo o el programa etc. Para que funcione se lo debes de "presentar" ya sea que pongas la ruta absoluta: C:\Users\tu\ayayay.exe o asegurarte que el ProcessBuilder tenga acceso al PATH del sistema y que tu exe esté ahí listado.

Espero que esto te sirva.

Saludos.

Sobre ProcessBuilder

Hola de nuevo,
He probado el process builder, sin embargo no hace nada, me marca el error siguiente:

El resultado fue: An unhandled exception occurred at 0x004020F5 :
Invalid file handle
0x004020F5
0x004076A9

El codigo que ocupo es este:

 Process p=new ProcessBuilder("C:\\Documents and Settings\\user\\Mis documentos\\carpeta1\\algo.exe" ).start();
                                InputStream input = p.getInputStream();
                                p.waitFor();
                                System.out.println( "El resultado fue: "+ new Scanner( input ).useDelimiter("\\A").next() );

Creo que ese es un error de pascal, sin embargo, el programa en java no espera a que termine la ejecucion para hacer lo demás, la salida de ese programa debe sobreescribir un archivo de texto en base a otro, los dos los tengo en la misma ruta, y no lo hace. La ejecucion del programa desde la consola tarda aproximadamente 10 seg, y no marca ese error. Podria ser que estoy mandandolo a llamar mal?

Gracias por su ayuda

Imagen de JRichard

02 formas de interactuar con un exe

Hola.

Te enfrentas a 02 problemas:

1.- Si el exe al que debes llamar inicialmente, finaliza automáticamente después de realizar su tarea (en tu caso crear un archivo), el siguiente
codiguillo te servira:

public static void main(String[] args) {

        try {

            System.out.println("Inicio del Programa");

            Process p = Runtime.getRuntime().exec("ascii.exe");

            boolean no_exit = true;

            while(no_exit){

                try {
                    p.exitValue();
                    no_exit = false;
                }catch(IllegalThreadStateException exception){
                    no_exit=true;
                    System.out.println("El programa aun no finaliza");
                }
            }

            System.out.println("El programa finalizo");
           
            /*Inicio de las acciones que siguen a la finalizacion del exe*/

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

02.- Si el exe al que debes llamar inicialmente no finaliza automáticamente. Es decir después de realizar su tarea se queda esperando una acción
del usuario, tiene una gui ( boton cerrar ), muestra el mensaje de "Presione una tecla para continuar", etc

Si este es tu caso , se desencadenan 02 soluciones:

a.- Interactua con el .exe y despues que termine su tarea, terminalo, finalizalo o cierralo. Si haces esto el codiguillo de arriba te servira ya que automaticamente terminara el while(no_exit)

b.- Calcula aproximadamente cuanto tiempo se demora en realizar su tarea el .exe, luego termina el exe asi:

    public static void main(String[] args) {

        try {

            System.out.println("Inicio del Programa");

            Process p = Runtime.getRuntime().exec("ascii.exe");

            boolean no_exit = true;
            long hora_ini = (new Date()).getTime(); // numero de milisegundos
            long tiempo_proceso_exe = 5000; // 5 segundos

            while (no_exit) {

                try {
                    long hora_actual = (new Date()).getTime();
                    if ((hora_ini + tiempo_proceso_exe) < hora_actual) {
                        no_exit = false;
                    } else {
                        p.exitValue();
                        no_exit = false;
                    }

                } catch (IllegalThreadStateException exception) {
                    no_exit = true;
                    System.out.println("El programa aun no finaliza");
                }
            }

            // terminamos el proceso:
            p.destroy();

            System.out.println("El programa finalizo");

            /*Inicio de las acciones que siguen a la finalizacion del exe*/

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

No se si es optima la solucion, pero por ahora no se me ocurre otra.

Te adjunto proyecto netbeans junto con el exe que hice hace mil años en c++. Este exe muestra el ascii de los primeros 126 caracters.

http://hotfile.com/dl/142179578/ea21bfa/PruebaInteraccionExe.rar.html

Ojala te sirva de algo.

Saludos.