IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Execution de fichiers .bat sous java


Sujet :

Java

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 19
    Points : 11
    Points
    11
    Par défaut Execution de fichiers .bat sous java
    Bonjour,

    J'ai un programme sous format de deux fichier ".bat" et je veux l'exécuter à travers une application Java. Les détails des deux fichiers (setgen.bat et XMLGenerator.bat) sont les suivants:

    1. Fichier "setgen.bat":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    @echo off
    echo this release was tested with JDK 1.2, XML4Java 2_0_15.
    if "%xmlgen-root%" == "" for /f %%f in ('cd') do set xmlgen-root=%%f
    if "%xmlgen-classpath%" == "" set xmlgen-classpath=%classpath%
    set classpath=%xmlgen-root%\XMLGenerator.jar;%xmlgen-root%\xml4j.jar;%xmlgen-root%\DDbe.jar;%xmlgen-root%\jfaceall.jar;%xmlgen-classpath%
    if "%xmlgen-savedpath%" == "" set xmlgen-savedpath=%path%
    set path=%xmlgen-root%;%xmlgen-savedpath%
    echo Your classpath is %classpath%
    2. Fichier "XMLGenerator.bat":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    @echo off
    if ""=="%xmlgen-root%" goto fail
    java com.ibm.XMLGenerator.XMLGenerator %1 %2 %3 %4 %5 %6 %7 %8 %9
    goto done
    :fail
    echo please run setgen.bat from the install directory.
    :done
    Le premier fichier a pour but de définir certaines variables d'environnement qui sont utilisées par le deuxième. Le deuxième lance un certain fichier jar. Sous un terminal, je lance setgen.gat et puis XMLGenerator param_1 param_2....param_n et ça s'exécute sans aucun problème.

    Par contre je ne sais pas comment faire exécuter ces deux fichiers en utilisant un programme java.

    J'ai essayé avec le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    private void executeCommand(String directory){
    try {
         //Execution du premier fichier.
         File dir = new File(directory);
         Process p = Runtime.getRuntime().exec("cmd /c setgen", null, dir); 
         p.waitFor();
         BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
         String line1=reader.readLine();
         while(line1 != null){
               System.out.println(line1);
               line1=reader.readLine();
         }
     
         //Execution du deuxième fichier.
         p = Runtime.getRuntime().exec("cmd /c XMLGenerator param1 param2", null, dir); 
         p.waitFor();
         reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
         line1=reader.readLine();
         while(line1 != null){
               System.out.println(line1);
               line1=reader.readLine();
         }
    } catch (Exception ex){
           System.err.println("Error: "+ex.getMessage());
    }
        }
    Après l'exécution de cette méthode j’obtiens le message d'erreur: "please run setgen.bat from the install directory.", puisque chacun des deux fichier s'exécute dans un terminal différent de l'autre, et donc les variables d'environnement crées par le premier fichier ne sont plus utilisées par le deuxième, donc ce sont deux processus différents et indépendant ce qui n'est plus le cas du terminal où les variables crées peuvent être utilisées tant que le terminal est encore ouvert.

    Y a t-il une astuce pour combiner les deux fichiers ensemble ? ou pour les exécuter dans un même processus ?

    Merci d'avance.

  2. #2
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    C'est bon j'ai trouvé la solution, il fallait juste combiner les deux commandes avec un "&". La méthode devient donc comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    private void executeCommand(String directory){
    try {
         File dir = new File(directory);
         Process p = Runtime.getRuntime().exec("cmd /c setgen.bat & XMLGenerator param1 param2", null, dir); 
         p.waitFor();
         BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
         String line1=reader.readLine();
         while(line1 != null){
               System.out.println(line1);
               line1=reader.readLine();
         }
    } catch (Exception ex){
           System.err.println("Error: "+ex.getMessage());
    }
        }
    N'hésitez pas à me faire part de vos remarques.

    Merci et bonne journée.

  3. #3
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par Laurent_3154 Voir le message
    N'hésitez pas à me faire part de vos remarques.
    J'ai remarqué plusieurs petits problèmes dans ton code :
    • Tu utilises waitFor() juste après avoir lancer ton process.
      Du coup ton code va bloquer tant que le process ne sera pas terminé.

      C'est problématique car tu lis son flux de sortie après.
      Si les données envoyées sont de taille réduite ca passera sans problème, mais si le process écrit "trop" de données cela va remplir le buffer entre ton process et ton appli java, et tu va te retrouver dans un double-lock :
      • Ton appli Java attendra la fin du process (waitFor()).
      • Ton process sera bloqué en écriture à cause du buffer plein.


      Il faut bien entendu utiliser waitFor() après la lecture du flux de sortie.
    • Tu ne traites pas les flux d'entrée et d'erreur du process. Encore une fois tu risques de bloquer le process s'il les utilise.
      Il faut soit les traiter (en parallèle), soit les fermer (ce qui évitera les problèmes de blocage).


    Bref pour moi ton code devrait plutôt ressembler à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    	private void executeCommand(String directory) {
    		try {
    			File dir = new File(directory);
    			Process p = Runtime.getRuntime()
    					.exec("cmd /c setgen.bat & XMLGenerator param1 param2",
    							null, dir);
    			try {
    				p.getOutputStream().close();
    				p.getErrorStream().close();
     
    				BufferedReader reader = new BufferedReader(
    						new InputStreamReader(p.getInputStream()));
    				String line1 = reader.readLine();
    				while (line1 != null) {
    					System.out.println(line1);
    					line1 = reader.readLine();
    				}
    				p.waitFor();
    			} finally {
    				// perso j'aime bien forcé le destroy "au cas où"
    				p.destroy();
    			}
     
    		} catch (Exception ex) {
    			System.err.println("Error: " + ex.getMessage());
    		}
    	}

    Et si tu utilises Java 5.0 ou plus, il serait préférable d'utiliser ProcessBuilder à la place de Runtime.exec(), cela permet entre autre de séparer proprement les arguments de la commande, et surtout de rediriger le flux d'erreur dans le flux standard (ce qui permet de ne traiter qu'un flux sans perdre d'éventuel message d'erreur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    	private void executeCommand(String directory) {
    		try {
    			Process p = new ProcessBuilder("cmd", "/c", "setgen.bat & XMLGenerator param1 param2")
    				.directory(new File(directory))
    				.redirectErrorStream(true) // on redirige le flux d'erreur vers le flux de sortie
    				.start();
    			try {
    				p.getOutputStream().close();
    				p.getErrorStream().close();
     
    				BufferedReader reader = new BufferedReader(
    						new InputStreamReader(p.getInputStream()));
    				String line1 = reader.readLine();
    				while (line1 != null) {
    					System.out.println(line1);
    					line1 = reader.readLine();
    				}
    				p.waitFor();
    			} finally {
    				// perso j'aime bien forcé le destroy "au cas où"
    				p.destroy();
    			}
     
    		} catch (Exception ex) {
    			System.err.println("Error: " + ex.getMessage());
    		}
    	}

    Et avec Java 7 on peut même utiliser inheritIO() pour hériter des flux de l'application Java, et du coup plus besoin de les gérer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	private void executeCommand(String directory) {
    		try {
    			Process p = new ProcessBuilder("cmd", "/c", "setgen.bat & XMLGenerator param1 param2")
    				.directory(new File(directory))
    				.inheritIO()
    				.start();
    			p.waitFor();
    		} catch (Exception ex) {
    			System.err.println("Error: " + ex.getMessage());
    		}
    	}
    Note : on peut même paramétrer individuellement chaque flux avec les méthodes redirectXXX()


    a++

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,



    J'ai remarqué plusieurs petits problèmes dans ton code :
    • Tu utilises waitFor() juste après avoir lancer ton process.
      Du coup ton code va bloquer tant que le process ne sera pas terminé.

      C'est problématique car tu lis son flux de sortie après.
      Si les données envoyées sont de taille réduite ca passera sans problème, mais si le process écrit "trop" de données cela va remplir le buffer entre ton process et ton appli java, et tu va te retrouver dans un double-lock :
      • Ton appli Java attendra la fin du process (waitFor()).
      • Ton process sera bloqué en écriture à cause du buffer plein.


      Il faut bien entendu utiliser waitFor() après la lecture du flux de sortie.
    • Tu ne traites pas les flux d'entrée et d'erreur du process. Encore une fois tu risques de bloquer le process s'il les utilise.
      Il faut soit les traiter (en parallèle), soit les fermer (ce qui évitera les problèmes de blocage).


    Bref pour moi ton code devrait plutôt ressembler à ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    	private void executeCommand(String directory) {
    		try {
    			File dir = new File(directory);
    			Process p = Runtime.getRuntime()
    					.exec("cmd /c setgen.bat & XMLGenerator param1 param2",
    							null, dir);
    			try {
    				p.getOutputStream().close();
    				p.getErrorStream().close();
     
    				BufferedReader reader = new BufferedReader(
    						new InputStreamReader(p.getInputStream()));
    				String line1 = reader.readLine();
    				while (line1 != null) {
    					System.out.println(line1);
    					line1 = reader.readLine();
    				}
    				p.waitFor();
    			} finally {
    				// perso j'aime bien forcé le destroy "au cas où"
    				p.destroy();
    			}
     
    		} catch (Exception ex) {
    			System.err.println("Error: " + ex.getMessage());
    		}
    	}

    Et si tu utilises Java 5.0 ou plus, il serait préférable d'utiliser ProcessBuilder à la place de Runtime.exec(), cela permet entre autre de séparer proprement les arguments de la commande, et surtout de rediriger le flux d'erreur dans le flux standard (ce qui permet de ne traiter qu'un flux sans perdre d'éventuel message d'erreur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    	private void executeCommand(String directory) {
    		try {
    			Process p = new ProcessBuilder("cmd", "/c", "setgen.bat & XMLGenerator param1 param2")
    				.directory(new File(directory))
    				.redirectErrorStream(true) // on redirige le flux d'erreur vers le flux de sortie
    				.start();
    			try {
    				p.getOutputStream().close();
    				p.getErrorStream().close();
     
    				BufferedReader reader = new BufferedReader(
    						new InputStreamReader(p.getInputStream()));
    				String line1 = reader.readLine();
    				while (line1 != null) {
    					System.out.println(line1);
    					line1 = reader.readLine();
    				}
    				p.waitFor();
    			} finally {
    				// perso j'aime bien forcé le destroy "au cas où"
    				p.destroy();
    			}
     
    		} catch (Exception ex) {
    			System.err.println("Error: " + ex.getMessage());
    		}
    	}

    Et avec Java 7 on peut même utiliser inheritIO() pour hériter des flux de l'application Java, et du coup plus besoin de les gérer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	private void executeCommand(String directory) {
    		try {
    			Process p = new ProcessBuilder("cmd", "/c", "setgen.bat & XMLGenerator param1 param2")
    				.directory(new File(directory))
    				.inheritIO()
    				.start();
    			p.waitFor();
    		} catch (Exception ex) {
    			System.err.println("Error: " + ex.getMessage());
    		}
    	}
    Note : on peut même paramétrer individuellement chaque flux avec les méthodes redirectXXX()


    a++
    Bonjour,

    Je vous remercie infiniment, je vais prendre en considération toutes vos remarques pour améliorer mon code.

    Cordialement.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2011
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2011
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par Laurent_3154 Voir le message
    Bonjour,

    Je vous remercie infiniment, je vais prendre en considération toutes vos remarques pour améliorer mon code.

    Cordialement.
    Rebonjour,

    Savez-vous comment exécuter le même code sous Linux ? Y a t-il un moyen pour convertir mes deux fichiers .bat en fichiers sh ?

    Merci d'avance.

Discussions similaires

  1. executer un fichier .bat qui renvoi à un serveur via java
    Par credospirit dans le forum Développement Web en Java
    Réponses: 1
    Dernier message: 14/04/2014, 11h09
  2. Executer un fichier .bat sous linux
    Par misscricri dans le forum Applications et environnements graphiques
    Réponses: 1
    Dernier message: 22/08/2008, 19h41
  3. Réponses: 1
    Dernier message: 28/05/2008, 16h04
  4. execution d'un fichier *.bat sous excel
    Par anisr dans le forum Macros et VBA Excel
    Réponses: 12
    Dernier message: 27/02/2007, 12h41
  5. Executer un fichier .bat sur commande Démarrer/Arrêter
    Par loïc.rio dans le forum Windows
    Réponses: 5
    Dernier message: 10/05/2006, 16h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo