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.

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.


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.


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
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ć.


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.


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.


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. :(


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

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

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");

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();
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.