Wie führe ich eine Batchdatei aus meiner Java-Anwendung aus?

107

In meiner Java-Anwendung möchte ich eine Batchdatei ausführen, die " scons -Q implicit-deps-changed build\file_load_type export\file_load_type" aufruft.

Es scheint, dass ich nicht einmal meine Batch-Datei zum Ausführen bringen kann. Ich habe keine Ideen mehr.

Folgendes habe ich in Java:

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

Früher hatte ich eine Python-Sconscript-Datei, die ich ausführen wollte, aber da dies nicht funktionierte, beschloss ich, das Skript über eine Batch-Datei aufzurufen, aber diese Methode war noch nicht erfolgreich.

Amara
quelle

Antworten:

172

Batch-Dateien sind keine ausführbare Datei. Sie benötigen eine Anwendung, um sie auszuführen (z. B. cmd).

Unter UNIX hat die Skriptdatei am Anfang einer Datei shebang (#!), Um das Programm anzugeben, das sie ausführt. Ein Doppelklick in Windows wird vom Windows Explorer ausgeführt. CreateProcessweiß nichts darüber.

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

Hinweis: Mit dem start \"\"Befehl wird ein separates Befehlsfenster mit einem leeren Titel geöffnet und alle Ausgaben aus der Batchdatei werden dort angezeigt. Es sollte auch nur mit "cmd / c build.bat" funktionieren. In diesem Fall kann die Ausgabe auf Wunsch aus dem Unterprozess in Java gelesen werden.

Paulo Guedes
quelle
Für mich heißt es, dass Windows "build.bat" nicht finden kann. Wo soll ich diese Datei ablegen? Oder wie soll ich den Weg geben. Irgendwelche Vorschläge?
Nanospeck
1
Nehmen wir an, ich habe ein Array von Befehlen und iteriere dieses Array, um alle Befehle für (i = 0 bis command.length) {Runtime.getRuntime (). exec ("cmd / c start buil.bat") auszuführen. } Dann wird für jede Iteration (für jeden Befehl) ein Befehlsfenster geöffnet, was offensichtlich ist. Wie kann ich das vermeiden? Ich meine, alle Befehle in einem Fenster auszuführen.
viveksinghggits
1
Wir haben einen Code, der direkt "gradlew.bat" aufruft, ohne "cmd / c" davor zu setzen, und dieser Code funktioniert irgendwie. Ich denke also, dass Java oder Windows irgendwann einen Teil des Problems behoben haben. Wenn wir versuchen, "gradlew" auszuführen, schlägt dies jedoch fehl, so dass die ".bat" am Ende eindeutig noch benötigt wird.
Trejkaz
Win+R(Runtime) kann Batchdateien direkt ausführen.
Alex78191
21

Manchmal ist die Prozesszeit für die Thread-Ausführung höher als die Wartezeit für JVM-Threads. Dies geschieht, wenn die Verarbeitung des von Ihnen aufgerufenen Prozesses einige Zeit in Anspruch nimmt. Verwenden Sie den Befehl waitFor () wie folgt:

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     

}

Auf diese Weise wird die JVM angehalten, bis der von Ihnen aufgerufene Prozess abgeschlossen ist, bevor der Thread-Ausführungsstapel fortgesetzt wird.

Juan Carlos Alpízar
quelle
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
quelle
2
Es wäre nützlich, diesen Code zu kommentieren und uns zu sagen, warum und was der InputStream liest und warum es mich interessiert. Auch der Code für die Batch-Datei läuft gut, aber ich kann ihn nicht dazu bringen, eine Fehlerausnahme auszulösen.
Baruch Atta
2
Es würde mich verrückt machen, einen so verwirrenden Variablennamen wie "is" in meinem Code zu haben.
John Fisher
14

So führen Sie Batch-Dateien mit Java aus, wenn es sich um ...

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

Das sollte es tun.

Abbia
quelle
10
Die Frage wurde bereits mit einer funktionierenden Lösung beantwortet. Sie sollten nur Lösungen anbieten, von denen Sie wissen, dass sie funktionieren, und beschreiben, warum Ihre Lösung möglicherweise besser ist.
Smamatti
12

ProcessBuilder ist die Java 5/ 6-Methode zum Ausführen externer Prozesse.

Basszero
quelle
2
Warum ist der ProcessBuilder in Java 5/6 der richtige Weg?
Dan Polites
2
Interessante Wahl, um einen alten Beitrag wiederzubeleben ... ProcessBuilder bietet mehr Kontrolle, insbesondere die Möglichkeit, stderr einfach auf stdout umzuleiten. Ich finde das Setup auch intuitiver, aber das ist ein persönlicher Pref
Basszero
10

Die ausführbare Datei, die zum Ausführen von Batch-Skripten verwendet wird cmd.exe, verwendet das /cFlag, um den Namen der auszuführenden Batch-Datei anzugeben:

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

Theoretisch sollten Sie Scons auch auf diese Weise ausführen können, obwohl ich dies nicht getestet habe:

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

EDIT: Amara, du sagst, dass das nicht funktioniert. Der von Ihnen aufgeführte Fehler ist der Fehler, den Sie erhalten, wenn Sie Java von einem Cygwin-Terminal auf einer Windows-Box ausführen. machst du das Das Problem dabei ist, dass Windows und Cygwin unterschiedliche Pfade haben, sodass die Windows-Version von Java die ausführbaren Scons auf Ihrem Cygwin-Pfad nicht findet. Ich kann weiter erklären, ob sich dies als Ihr Problem herausstellt.

Eli Courtwright
quelle
Danke dir. Es funktioniert immer noch nicht - dieser Code wird in meiner App nicht einmal ausgeführt. Ich werde die andere Option ausprobieren, die Sie vorgestellt haben. Danke noch einmal.
Amara
Wenn ich die zweite Alternative versuche, wird folgende Fehlermeldung angezeigt: Ausnahme im Thread "main" java.io.IOException: Programm "scons" kann nicht ausgeführt werden: CreateProcess error = 2, Das System kann die angegebene Datei nicht finden
Amara
Nein, ich habe kein Cygwin-Terminal. Ich benutze Windows Command Terminal. Es ist seltsam - ich weiß nicht, warum es nicht funktionieren würde. Es verwirrt mich völlig.
Amara
3
Process p = Runtime.getRuntime().exec( 
  new String[]{"cmd", "/C", "orgreg.bat"},
  null, 
  new File("D://TEST//home//libs//"));

getestet mit jdk1.5 und jdk1.6

Das hat bei mir gut funktioniert, hoffe es hilft auch anderen. Um dies zu bekommen, habe ich mehr Tage gekämpft. :((

Suren
quelle
1
add this ==> BufferedReader reader = neuer BufferedReader (neuer InputStreamReader (p.getInputStream ())); String line = reader.readLine (); while (Zeile! = null) {System.out.println (Zeile); line = reader.readLine (); }
Suren
2

Ich hatte das gleiche Problem. Manchmal konnte CMD meine Dateien jedoch nicht ausführen. Deshalb erstelle ich eine temp.bat auf meinem Desktop, als nächstes wird diese temp.bat meine Datei ausführen und als nächstes wird die temporäre Datei gelöscht.

Ich weiß, dass dies ein größerer Code ist, der jedoch zu 100% für mich funktioniert hat, als sogar Runtime.getRuntime (). Exec () fehlgeschlagen ist.

// 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
quelle
1

Folgendes funktioniert einwandfrei:

String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
Bharath
quelle
Was bedeutet das / c?
Amal lal TL
0

Dieser Code führt zwei Befehle aus .bat, die im Pfad C: / folders / folder vorhanden sind.

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

Um die Antwort von @ Isha zu erweitern, können Sie einfach die folgenden Schritte ausführen , um die zurückgegebene Ausgabe (post-facto nicht in Echtzeit) des ausgeführten Skripts zu erhalten:

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