Come posso eseguire un file batch dalla mia applicazione Java?


107

Nella mia applicazione Java, voglio eseguire un file batch che richiami " scons -Q implicit-deps-changed build\file_load_type export\file_load_type"

Sembra che non riesca nemmeno a far eseguire il mio file batch. Sono a corto di idee.

Questo è quello che ho in Java:

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

In precedenza, avevo un file Python Sconscript che volevo eseguire, ma poiché non funzionava, ho deciso di chiamare lo script tramite un file batch ma quel metodo non ha ancora avuto successo.

Risposte:


172

I file batch non sono un eseguibile. Hanno bisogno di un'applicazione per eseguirli (es. Cmd).

In UNIX, il file di script ha un simbolo (#!) All'inizio di un file per specificare il programma che lo esegue. Il doppio clic in Windows viene eseguito da Windows Explorer. CreateProcessnon ne sa niente.

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

Nota: con il start \"\"comando, verrà aperta una finestra di comando separata con un titolo vuoto e qualsiasi output del file batch verrà visualizzato lì. Dovrebbe funzionare anche solo con `cmd / c build.bat", nel qual caso l'output può essere letto dal sottoprocesso in Java, se lo si desidera.


Per me dice che Windows non riesce a trovare "build.bat". Allora dove dovrei mettere questo file? O come dovrei dare il percorso. Eventuali suggerimenti?
nanospeck

1
diciamo che ho un array di comandi e quindi iterando quell'array per eseguire tutti i comandi per (i = 0 to commands.length) {Runtime.getRuntime (). exec ("cmd / c start buil.bat"); } quindi per ogni iterazione (per ogni comando) viene aperta una finestra di comando, il che è ovvio. Come evitarlo intendo eseguire tutti i comandi su una finestra.
viveksinghggits

1
Abbiamo del codice che chiama direttamente "gradlew.bat" senza mettere le cose "cmd / c" davanti, e quel codice funziona in qualche modo. Quindi immagino che Java o Windows abbiano risolto una parte del problema ad un certo punto. Se proviamo a eseguire "gradlew", ciò fallisce, quindi chiaramente il ".bat" è ancora necessario alla fine.
Trejkaz,

Win+R(Runtime) può eseguire direttamente i file batch.
Alex78191

21

A volte il tempo del processo di esecuzione del thread è superiore al tempo del processo di attesa del thread JVM, accade quando il processo che stai invocando richiede del tempo per essere elaborato, usa il comando waitFor () come segue:

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     

}

In questo modo la JVM si fermerà fino a quando il processo che stai invocando non sarà completato prima di continuare con lo stack di esecuzione del thread.


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

2
Sarebbe utile commentare questo codice e dirci perché e cosa sta leggendo InputStream, e perché mi interessa. Inoltre, il codice per il file batch funziona correttamente, ma non riesco a far sì che generi un'eccezione di errore.
Baruch Atta

2
Mi farebbe impazzire avere un nome di variabile così confuso come "is" nel mio codice.
John Fisher

14

Per eseguire file batch utilizzando java se stai parlando di ...

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

Questo dovrebbe bastare.


10
Alla domanda è già stata data una risposta con una soluzione funzionante. Dovresti offrire solo le soluzioni che sai funzionano e descrivere perché pensi che la tua soluzione potrebbe essere migliore.
Smamatti

12

ProcessBuilder è il modo Java 5/6 per eseguire processi esterni.


2
Perché ProcessBuilder è la strada da percorrere in Java 5/6?
Dan Polites

2
Scelta interessante per resuscitare un vecchio post ... ProcessBuilder offre più controllo, in particolare la capacità di reindirizzare facilmente stderr a stdout. Trovo anche il setup più intuitivo, ma è una
prefazione

10

L'eseguibile utilizzato per eseguire gli script batch è cmd.exeche utilizza il /cflag per specificare il nome del file batch da eseguire:

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

Teoricamente dovresti anche essere in grado di eseguire Scons in questo modo, anche se non l'ho testato:

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

EDIT: Amara, dici che questo non funziona. L'errore che hai elencato è l'errore che avresti ottenuto eseguendo Java da un terminale Cygwin su una macchina Windows; è questo quello che stai facendo? Il problema è che Windows e Cygwin hanno percorsi diversi, quindi la versione Windows di Java non troverà l'eseguibile scons sul tuo percorso Cygwin. Posso spiegare ulteriormente se questo risulta essere il tuo problema.


Grazie. Ancora non funziona: quel pezzo di codice non viene nemmeno eseguito nella mia app. Proverò l'altra opzione che hai presentato. Grazie ancora.
Amara

Quando provo la seconda alternativa mi dà questo errore: Eccezione nel thread "main" java.io.IOException: Impossibile eseguire il programma "scons": Errore CreateProcess = 2, Il sistema non riesce a trovare il file specificato
Amara

No, non ho il terminale Cygwin. Uso il terminale di comando di Windows. È strano, non so perché non funzionerebbe. Mi sconcerta completamente.
Amara

3
Process p = Runtime.getRuntime().exec( 
  new String[]{"cmd", "/C", "orgreg.bat"},
  null, 
  new File("D://TEST//home//libs//"));

testato con jdk1.5 e jdk1.6

Questo funzionava bene per me, spero che aiuti anche gli altri. per ottenerlo ho faticato più giorni. :(


1
aggiungi questo ==> BufferedReader reader = new BufferedReader (new InputStreamReader (p.getInputStream ())); String line = reader.readLine (); while (riga! = null) {System.out.println (riga); riga = reader.readLine (); }
Suren

2

Ho avuto lo stesso problema. Tuttavia, a volte CMD non è riuscito a eseguire i miei file. Ecco perché creo un temp.bat sul mio desktop, dopo questo temp.bat eseguirà il mio file e successivamente il file temporaneo verrà eliminato.

So che questo è un codice più grande, tuttavia ha funzionato per me al 100% quando anche Runtime.getRuntime (). Exec () falliva.

// 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();

1

Quanto segue funziona bene:

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

cosa significa / c?
Amal lal TL

0

Questo codice eseguirà due commands.bat che esistono nel percorso C: / cartelle / cartella.

Runtime.getRuntime().exec("cd C:/folders/folder & call commands.bat");

0

Per espandere la risposta di @ Isha puoi semplicemente fare quanto segue per ottenere l'output restituito (post-facto non in tempo reale) dello script che è stato eseguito:

try {
    Process process = Runtime.getRuntime().exec("cmd /c start D:\\temp\\a.bat");
    System.out.println(process.getText());
} catch(IOException e) {
    e.printStackTrace();
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.