2017-07-12 5 views
0

Je n'arrive pas à démarrer une application à partir de mon interface graphique JavaFX. J'utilise ProcessBuilder. Cela crée le processus, mais l'application ne sera pas lancée avant la fermeture de mon programme Java. Est-ce parce que ce programme spécifique attend des arguments ou quelque chose qui ne va pas avec mon code?Démarrage d'une application externe dans Java

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

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

} 

L'application externe démarre mais ne permet aucune interaction avec l'application d'origine tant que je n'ai pas fermé ce programme externe. J'ai essayé d'exécuter un nouveau thread, même résultat. Voici le nouveau 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(); 
     } 
+0

Où gérez-vous les flux générés par le processus? C'est l'une des premières choses que je ferais ici, et pour m'assurer que mon processus fonctionne dans son propre thread. –

+0

Cette application externe n'est pas censée renvoyer des données à mon application, ai-je encore besoin de gérer les flux? Donc je dois spécifier qu'il fonctionne sur un autre thread? Je pensais que c'était déjà fait parce que quand je ferme mon application, l'application externe reste en cours d'exécution (commence réellement à courir). Désolé je suis relativement nouveau à ceci. Merci. –

+0

Oui, vous devez absolument gérer les flux, sinon l'application risque de manquer de mémoire tampon, ce qui risque de provoquer un blocage. S'il vous plaît lire [Lorsque Runtime.exec() ne sera pas] (http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html). L'article contient des informations datées (n'utilisant pas ProcessBuilder pour un), mais la plupart des informations qu'il contient sont exactes. –

Répondre

2

Lire cet article, bonne information. Lisez aussi un autre bon exemple ici. Il fonctionne dans un nouveau thread maintenant, mais mon programme attend que l'application externe se termine avant de continuer, je comprends que c'est généralement souhaité, mais pas dans ce cas, comment puis-je désactiver cela? Attendez la production de la valeur de sortie dans un nouveau thread.

Quelque chose comme:

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(); 
} 
+0

Cela fonctionne parfaitement, Les commentaires sont très utiles pour expliquer tout, donc je dois créer un fil différent pour gérer la valeur de sortie si je ne veux pas que mon programme attende correctement? –

+0

@Karodarmoyan: oui –