Jak uruchomić plik wsadowy z mojej aplikacji Java?

107

W mojej aplikacji Java chcę uruchomić plik wsadowy, który wywołuje „ scons -Q implicit-deps-changed build\file_load_type export\file_load_type

Wygląda na to, że nie mogę nawet uruchomić mojego pliku wsadowego. Nie mam pomysłów.

Oto, co mam w Javie:

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

Wcześniej miałem plik Python Sconscript, który chciałem uruchomić, ale ponieważ to nie zadziałało, zdecydowałem, że wywołam skrypt za pośrednictwem pliku wsadowego, ale ta metoda jeszcze się nie powiodła.

Amara
źródło

Odpowiedzi:

172

Pliki wsadowe nie są plikami wykonywalnymi. Potrzebują aplikacji do ich uruchomienia (np. Cmd).

W systemie UNIX plik skryptu ma na początku pliku shebang (#!), Aby określić program, który go wykonuje. Dwukrotne kliknięcie w systemie Windows jest wykonywane przez Eksploratora Windows. CreateProcessnic o tym nie wie.

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

Uwaga: za pomocą tego start \"\"polecenia zostanie otwarte oddzielne okno poleceń z pustym tytułem, w którym zostaną wyświetlone wszelkie dane wyjściowe z pliku wsadowego. Powinien również działać tylko z `cmd / c build.bat", w którym to przypadku wynik może być w razie potrzeby odczytany z podprocesu w Javie.

Paulo Guedes
źródło
Dla mnie oznacza to, że system Windows nie może znaleźć pliku „build.bat”. Więc gdzie mam umieścić ten plik? Albo jak mam wytyczyć ścieżkę. Jakieś sugestie?
nanospeck
1
powiedzmy, że mam tablicę poleceń, a następnie iteruję tę tablicę, aby wykonać wszystkie polecenia dla (i = 0 do commands.length) {Runtime.getRuntime (). exec ("cmd / c start buil.bat"); } następnie dla każdej iteracji (dla każdego polecenia) otwiera się okno poleceń, co jest oczywiste. Jak można tego uniknąć, mam na myśli wykonywanie wszystkich poleceń w jednym oknie.
viveksinghggits
1
Mamy kod, który bezpośrednio wywołuje „gradlew.bat” bez umieszczania przed nim elementów „cmd / c” i ten kod jakoś działa. Więc wydaje mi się, że w pewnym momencie albo Java, albo Windows naprawiły część problemu. Jeśli spróbujemy wykonać „gradlew”, to się nie powiedzie, więc najwyraźniej „.bat” jest nadal potrzebny na końcu.
Trejkaz
Win+R(Runtime) może bezpośrednio uruchamiać pliki wsadowe.
Alex78191
21

Czasami czas wykonywania wątku jest dłuższy niż czas oczekiwania na wątek maszyny JVM; zdarza się, gdy proces, który wywołujesz, zajmuje trochę czasu, użyj polecenia waitFor () w następujący sposób:

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     

}

W ten sposób maszyna JVM zatrzyma się, dopóki wywoływany proces nie zostanie zakończony, zanim będzie kontynuowany ze stosem wykonywania wątków.

Juan Carlos Alpízar
źródło
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
źródło
2
Przydałoby się skomentować ten kod i powiedzieć nam, dlaczego i co czyta InputStream i dlaczego mnie to obchodzi. Ponadto kod pliku wsadowego działa dobrze, ale nie mogę go zmusić do wywołania wyjątku błędu.
Baruch Atta
2
Doprowadziłoby mnie do szału, mając w kodzie tak mylącą nazwę zmiennej, jak „jest”.
John Fisher,
14

Aby uruchomić pliki wsadowe za pomocą javy, jeśli o tym mowa ...

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

To powinno wystarczyć.

Abbia
źródło
10
Na pytanie zostało już udzielone działające rozwiązanie. Powinieneś oferować tylko rozwiązania, o których wiesz, że działają, i opisać, dlaczego uważasz, że Twoje rozwiązanie może być lepsze.
Smamatti
12

ProcessBuilder to metoda Java 5/6 do uruchamiania procesów zewnętrznych.

basszero
źródło
2
Dlaczego ProcessBuilder jest właściwą drogą w Javie 5/6?
Dan Polites
2
Ciekawy wybór, aby wskrzesić stary post ... ProcessBuilder oferuje większą kontrolę, w szczególności możliwość łatwego przekierowania stderr na stdout. Uważam również, że konfiguracja jest bardziej intuicyjna, ale to osobisty
wstęp
10

Plik wykonywalny używany do uruchamiania skryptów wsadowych cmd.exeużywa /cflagi do określenia nazwy pliku wsadowego do uruchomienia:

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

Teoretycznie powinieneś być w stanie uruchomić Scons w ten sposób, chociaż nie testowałem tego:

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

EDYCJA: Amara, mówisz, że to nie działa. Błąd, który podałeś, to błąd, który otrzymasz podczas uruchamiania Javy z terminala Cygwin na komputerze z systemem Windows; czy to właśnie robisz? Problem polega na tym, że Windows i Cygwin mają różne ścieżki, więc wersja Java dla systemu Windows nie znajdzie pliku wykonywalnego scons na ścieżce Cygwin. Mogę wyjaśnić dalej, jeśli okaże się, że to twój problem.

Eli Courtwright
źródło
Dziękuję Ci. Nadal nie działa - ten fragment kodu nawet nie działa w mojej aplikacji. Spróbuję innej przedstawionej opcji. Dzięki jeszcze raz.
Amara
Kiedy próbuję drugi wariant daje mi ten błąd: Exception w wątku „main” java.io.IOException: Nie można uruchomić programu „scons”: błąd CreateProcess = 2, system nie może odnaleźć określonego pliku
Amara
Nie, nie mam terminala Cygwin. Używam terminala poleceń systemu Windows. To dziwne - nie wiem, dlaczego to nie zadziała. Całkowicie mnie to zaskakuje.
Amara
3
Process p = Runtime.getRuntime().exec( 
  new String[]{"cmd", "/C", "orgreg.bat"},
  null, 
  new File("D://TEST//home//libs//"));

testowane z jdk1.5 i jdk1.6

To działało dobrze dla mnie, mam nadzieję, że pomaga też innym. aby to uzyskać, walczyłem przez więcej dni. :(

Jasne
źródło
1
dodaj this ==> BufferedReader reader = new BufferedReader (new InputStreamReader (p.getInputStream ())); String line = reader.readLine (); while (linia! = null) {System.out.println (linia); line = reader.readLine (); }
Suren
2

Miałem ten sam problem. Jednak czasami CMD nie mógł uruchomić moich plików. Dlatego tworzę temp.bat na moim pulpicie, następnie ten temp.bat uruchomi mój plik, a następnie plik tymczasowy zostanie usunięty.

Wiem, że jest to większy kod, ale działał u mnie w 100%, gdy nawet Runtime.getRuntime (). Exec () zawiódł.

// 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
źródło
1

Następujące działa dobrze:

String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
bharath
źródło
co oznacza / c?
Amal lal TL
0

Ten kod wykona dwa polecenia.bat, które istnieją w ścieżce C: / foldery / folder.

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

Aby rozwinąć odpowiedź @ Isha, możesz po prostu wykonać następujące czynności, aby uzyskać zwrócony wynik (po fakcie, a nie w czasie rzeczywistym) skryptu, który został uruchomiony:

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