Como executo um arquivo em lote do meu aplicativo Java?

107

Em meu aplicativo Java, desejo executar um arquivo em lote que chama " scons -Q implicit-deps-changed build\file_load_type export\file_load_type"

Parece que não consigo nem mesmo fazer meu arquivo em lote executar. Estou sem ideias.

Isso é o que tenho em Java:

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

Anteriormente, eu tinha um arquivo Python Sconscript que queria executar, mas como isso não funcionou, decidi que chamaria o script por meio de um arquivo em lote, mas esse método ainda não teve sucesso.

Amara
fonte

Respostas:

172

Os arquivos em lote não são executáveis. Eles precisam de um aplicativo para executá-los (ou seja, cmd).

No UNIX, o arquivo de script tem shebang (#!) No início de um arquivo para especificar o programa que o executa. O clique duplo no Windows é executado pelo Windows Explorer. CreateProcessnão sabe nada sobre isso.

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

Nota: Com o start \"\"comando, uma janela de comando separada será aberta com um título em branco e qualquer saída do arquivo em lote será exibida lá. Ele também deve funcionar apenas com `cmd / c build.bat", caso em que a saída pode ser lida do subprocesso em Java, se desejado.

Paulo Guedes
fonte
Para mim, diz que o Windows não consegue encontrar "build.bat". Então, onde devo colocar esse arquivo? Ou como devo indicar o caminho. Alguma sugestão?
nanospeck de
1
digamos que eu tenha uma matriz de comandos e, em seguida, iterando essa matriz para executar todos os comandos para (i = 0 a commands.length) {Runtime.getRuntime (). exec ("cmd / c start buil.bat"); } então, para cada iteração (para cada comando), uma janela de comando é aberta, o que é óbvio. Como posso evitar isso, quero dizer executar todos os comandos em uma janela.
viveksinghggits
1
Temos um código que está chamando diretamente "gradlew.bat" sem colocar "cmd / c" antes dele, e esse código está funcionando de alguma forma. Portanto, acho que o Java ou o Windows corrigiram parte do problema em algum momento. Se tentarmos executar "gradlew", isso falhará, então claramente o ".bat" ainda é necessário no final.
Trejkaz
Win+R(Runtime) pode executar arquivos em lote diretamente.
Alex78191
21

Às vezes, o tempo do processo de execução do encadeamento é maior do que o tempo do processo de espera do encadeamento da JVM. Isso costuma acontecer quando o processo que você está chamando leva algum tempo para ser processado, use o comando waitFor () da seguinte maneira:

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     

}

Dessa forma, a JVM irá parar até que o processo que você está chamando seja concluído, antes de continuar com a pilha de execução do encadeamento.

Juan Carlos Alpízar
fonte
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
fonte
2
Seria útil comentar este código e nos dizer por que e o que o InputStream está lendo e por que me importo. Além disso, o código do arquivo em lote está funcionando bem, mas não consigo fazer com que ele gere uma exceção de erro.
Baruch Atta
2
Isso me deixaria louco ter um nome de variável tão confuso como "é" em meu código.
John Fisher
14

Para executar arquivos em lote usando java, se é isso que você está falando ...

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

Isso deve servir.

Abbia
fonte
10
A pergunta já foi respondida com uma solução funcional. Você deve oferecer apenas soluções que você sabe que estão funcionando e descrever por que acha que sua solução pode ser melhor.
Smamatti de
12

ProcessBuilder é a maneira Java 5/6 de executar processos externos.

basszero
fonte
2
Por que o ProcessBuilder é a melhor opção no Java 5/6?
Dan Polites
2
Escolha interessante para ressuscitar um post antigo ... ProcessBuilder oferece mais controle, especificamente a capacidade de redirecionar facilmente stderr para stdout. Também acho a configuração mais intuitiva, mas é uma preferência pessoal
basszero
10

O executável usado para executar scripts em lote é cmd.exeaquele que usa o /csinalizador para especificar o nome do arquivo em lote a ser executado:

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

Teoricamente, você também deve ser capaz de executar Scons dessa maneira, embora eu não tenha testado isso:

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

EDIT: Amara, você diz que isso não está funcionando. O erro que você listou é o erro que você obteria ao executar o Java de um terminal Cygwin em uma caixa do Windows; é isso que você está fazendo? O problema com isso é que o Windows e o Cygwin têm caminhos diferentes, então a versão do Java para Windows não encontrará o executável scons no caminho do Cygwin. Posso explicar melhor se esse for o seu problema.

Eli Courtwright
fonte
Obrigado. Ainda não funciona - aquele pedaço de código nem mesmo é executado no meu aplicativo. Vou tentar a outra opção que você apresentou. Obrigado novamente.
Amara
Quando tento a segunda alternativa, recebo este erro: Exceção no thread "main" java.io.IOException: Não é possível executar o programa "scons": erro CreateProcess = 2, O sistema não pode encontrar o arquivo especificado
Amara
Não, eu não tenho terminal Cygwin. Eu uso o terminal de comando do Windows. É estranho - não sei por que não funcionaria. Isso me deixa completamente perplexo.
Amara
3
Process p = Runtime.getRuntime().exec( 
  new String[]{"cmd", "/C", "orgreg.bat"},
  null, 
  new File("D://TEST//home//libs//"));

testado com jdk1.5 e jdk1.6

Isso estava funcionando bem para mim, espero que ajude outras pessoas também. para conseguir isso, lutei mais dias. :(

Suren
fonte
1
adicione este ==> leitor BufferedReader = new BufferedReader (new InputStreamReader (p.getInputStream ())); Linha de string = leitor.readLine (); while (linha! = null) {System.out.println (linha); linha = leitor.readLine (); }
Suren
2

Eu tive o mesmo problema. No entanto, às vezes o CMD falhava ao executar meus arquivos. É por isso que eu crio um temp.bat na minha área de trabalho. Em seguida, esse temp.bat executará meu arquivo e, em seguida, o arquivo temporário será excluído.

Eu sei que este é um código maior, porém funcionou para mim em 100% quando até mesmo Runtime.getRuntime (). Exec () falhou.

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

O seguinte está funcionando bem:

String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
bharath
fonte
o que o / c significa?
Amal lal TL
0

Este código executará dois commands.bat que existem no caminho C: / folders / folder.

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

Para expandir a resposta de @Isha, você pode simplesmente fazer o seguinte para obter a saída retornada (post-facto, não em tempo real) do script que foi executado:

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