Comment exécuter un fichier de commandes à partir de mon application Java?

107

Dans mon application Java, je souhaite exécuter un fichier batch qui appelle " scons -Q implicit-deps-changed build\file_load_type export\file_load_type"

Il semble que je ne parviens même pas à exécuter mon fichier batch. Je suis à court d'idées.

Voici ce que j'ai en Java:

Runtime.
   getRuntime().
   exec("build.bat", null, new File("."));

Auparavant, j'avais un fichier Python Sconscript que je voulais exécuter mais comme cela ne fonctionnait pas, j'ai décidé d'appeler le script via un fichier de commandes, mais cette méthode n'a pas encore réussi.

Amara
la source

Réponses:

172

Les fichiers batch ne sont pas un exécutable. Ils ont besoin d'une application pour les exécuter (c'est-à-dire cmd).

Sous UNIX, le fichier de script a shebang (#!) Au début d'un fichier pour spécifier le programme qui l'exécute. Le double-clic dans Windows est effectué par l'Explorateur Windows. CreateProcessne sait rien à ce sujet.

Runtime.
   getRuntime().
   exec("cmd /c start \"\" build.bat");

Remarque: Avec la start \"\"commande, une fenêtre de commande distincte sera ouverte avec un titre vide et toute sortie du fichier de commandes y sera affichée. Il devrait également fonctionner uniquement avec `cmd / c build.bat", auquel cas la sortie peut être lue depuis le sous-processus en Java si vous le souhaitez.

Paulo Guedes
la source
Pour moi, cela dit que Windows ne peut pas trouver "build.bat". Alors, où dois-je mettre ce fichier? Ou comment devrais-je donner le chemin. Aucune suggestion?
nanospeck
1
disons que j'ai un tableau de commandes et ensuite itérer ce tableau pour exécuter toutes les commandes pour (i = 0 à commands.length) {Runtime.getRuntime (). exec ("cmd / c start buil.bat"); } puis pour chaque itération (pour chaque commande) une fenêtre de commande s'ouvre, ce qui est évident. Comment éviter cela, je veux dire exécuter toutes les commandes sur une seule fenêtre.
viveksinghggits
1
Nous avons un code qui appelle directement "gradlew.bat" sans mettre "cmd / c" devant lui, et ce code fonctionne d'une manière ou d'une autre. Je suppose donc que Java ou Windows a résolu une partie du problème à un moment donné. Si nous essayons d'exécuter "gradlew", cela échoue cependant, il est donc clair que le ".bat" est toujours nécessaire à la fin.
Trejkaz du
Win+R(Runtime) peut exécuter directement des fichiers batch.
Alex78191
21

Parfois, le temps du processus d'exécution du thread est supérieur au temps du processus d'attente du thread JVM, cela se produit lorsque le processus que vous appelez prend un certain temps à être traité, utilisez la commande waitFor () comme suit:

try{    
    Process p = Runtime.getRuntime().exec("file location here, don't forget using / instead of \\ to make it interoperable");
    p.waitFor();

}catch( IOException ex ){
    //Validate the case the file can't be accesed (not enought permissions)

}catch( InterruptedException ex ){
    //Validate the case the process is being stopped by some external situation     

}

De cette façon, la JVM s'arrêtera jusqu'à ce que le processus que vous invoquez soit terminé avant de continuer avec la pile d'exécution de thread.

Juan Carlos Alpízar
la source
20
Runtime runtime = Runtime.getRuntime();
try {
    Process p1 = runtime.exec("cmd /c start D:\\temp\\a.bat");
    InputStream is = p1.getInputStream();
    int i = 0;
    while( (i = is.read() ) != -1) {
        System.out.print((char)i);
    }
} catch(IOException ioException) {
    System.out.println(ioException.getMessage() );
}
Isha
la source
2
Il serait utile de commenter ce code et de nous dire pourquoi et ce que lit InputStream, et pourquoi je m'en soucie. En outre, le code du fichier de commandes fonctionne correctement, mais je ne parviens pas à le faire générer une exception d'erreur.
Baruch Atta
2
Cela me rendrait fou d'avoir un nom de variable aussi déroutant que «est» dans mon code.
John Fisher
14

Pour exécuter des fichiers de commandes en utilisant java si vous parlez de ...

String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);`

Cela devrait le faire.

Abbia
la source
10
La question a déjà reçu une réponse avec une solution de travail. Vous ne devez proposer que des solutions dont vous savez qu'elles fonctionnent et expliquer pourquoi vous pensez que votre solution pourrait être meilleure.
Smamatti
12

ProcessBuilder est le moyen Java 5/6 d'exécuter des processus externes.

basszero
la source
2
Pourquoi ProcessBuilder est-il la voie à suivre dans Java 5/6?
Dan Polites
2
Choix intéressant pour ressusciter un ancien poste ... ProcessBuilder offre plus de contrôle, en particulier la possibilité de rediriger facilement stderr vers stdout. Je trouve également la configuration plus intuitive, mais c'est une préférence personnelle
basszero
10

L'exécutable utilisé pour exécuter les scripts batch est celui cmd.exequi utilise l' /cindicateur pour spécifier le nom du fichier batch à exécuter:

Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "build.bat"});

Théoriquement, vous devriez également pouvoir exécuter Scons de cette manière, même si je n'ai pas testé ceci:

Runtime.getRuntime().exec(new String[]{"scons", "-Q", "implicit-deps-changed", "build\file_load_type", "export\file_load_type"});

EDIT: Amara, vous dites que cela ne fonctionne pas. L'erreur que vous avez répertoriée est l'erreur que vous obtiendrez lors de l'exécution de Java à partir d'un terminal Cygwin sur une boîte Windows; est-ce ce que vous faites? Le problème avec cela est que Windows et Cygwin ont des chemins différents, donc la version Windows de Java ne trouvera pas l'exécutable scons sur votre chemin Cygwin. Je peux vous expliquer davantage si cela s'avère être votre problème.

Eli Courtwright
la source
Je vous remercie. Cela ne fonctionne toujours pas - ce morceau de code ne s'exécute même pas dans mon application. J'essaierai l'autre option que vous avez présentée. Merci encore.
Amara
Lorsque j'essaie la deuxième alternative, cela me donne cette erreur: Exception dans le fil "main" java.io.IOException: Impossible d'exécuter le programme "scons": Erreur CreateProcess = 2, Le système ne trouve pas le fichier spécifié
Amara
Non, je n'ai pas de terminal Cygwin. J'utilise le terminal de commande Windows. C'est étrange - je ne sais pas pourquoi cela ne fonctionnerait pas. Cela me déroute complètement.
Amara
3
Process p = Runtime.getRuntime().exec( 
  new String[]{"cmd", "/C", "orgreg.bat"},
  null, 
  new File("D://TEST//home//libs//"));

testé avec jdk1.5 et jdk1.6

Cela fonctionnait bien pour moi, j'espère que cela aidera les autres aussi. pour obtenir cela, j'ai lutté plus de jours. :(

Suren
la source
1
ajoutez ceci ==> Lecteur BufferedReader = nouveau BufferedReader (nouveau InputStreamReader (p.getInputStream ())); Ligne de chaîne = reader.readLine (); while (ligne! = null) {System.out.println (ligne); ligne = lecteur.readLine (); }
Suren
2

J'ai eu le même problème. Cependant, parfois, CMD n'a pas réussi à exécuter mes fichiers. C'est pourquoi je crée un temp.bat sur mon bureau, ensuite ce temp.bat va exécuter mon fichier, et ensuite le fichier temporaire va être supprimé.

Je sais que c'est un code plus gros, mais a fonctionné pour moi à 100% lorsque même Runtime.getRuntime (). Exec () a échoué.

// creating a string for the Userprofile (either C:\Admin or whatever)
String userprofile = System.getenv("USERPROFILE");

BufferedWriter writer = null;
        try {
            //create a temporary file
            File logFile = new File(userprofile+"\\Desktop\\temp.bat");   
            writer = new BufferedWriter(new FileWriter(logFile));

            // Here comes the lines for the batch file!
            // First line is @echo off
            // Next line is the directory of our file
            // Then we open our file in that directory and exit the cmd
            // To seperate each line, please use \r\n
            writer.write("cd %ProgramFiles(x86)%\\SOME_FOLDER \r\nstart xyz.bat \r\nexit");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // Close the writer regardless of what happens...
                writer.close();
            } catch (Exception e) {
            }

        }

        // running our temp.bat file
        Runtime rt = Runtime.getRuntime();
        try {

            Process pr = rt.exec("cmd /c start \"\" \""+userprofile+"\\Desktop\\temp.bat" );
            pr.getOutputStream().close();
        } catch (IOException ex) {
            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);

        }
        // deleting our temp file
        File databl = new File(userprofile+"\\Desktop\\temp.bat");
        databl.delete();
Ben Jost
la source
1

Ce qui suit fonctionne bien:

String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
bharat
la source
que signifie le / c?
Amal lal TL
0

Ce code exécutera deux commandes.bat qui existent dans le chemin C: / folders / folder.

Runtime.getRuntime().exec("cd C:/folders/folder & call commands.bat");
رامي عبد الله
la source
0

Pour développer la réponse de @ Isha, vous pouvez simplement faire ce qui suit pour obtenir la sortie renvoyée (post-facto pas en temps réel) du script qui a été exécuté:

try {
    Process process = Runtime.getRuntime().exec("cmd /c start D:\\temp\\a.bat");
    System.out.println(process.getText());
} catch(IOException e) {
    e.printStackTrace();
}
NoodleOfDeath
la source