Làm cách nào để chạy một tệp hàng loạt từ Ứng dụng Java của tôi?


107

Trong ứng dụng Java của mình, tôi muốn chạy một tệp hàng loạt có tên " scons -Q implicit-deps-changed build\file_load_type export\file_load_type"

Có vẻ như tôi thậm chí không thể thực thi tệp hàng loạt của mình. Tôi hết ý tưởng.

Đây là những gì tôi có trong Java:

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

Trước đây, tôi có một tệp Python Sconscript mà tôi muốn chạy nhưng vì điều đó không hoạt động nên tôi quyết định sẽ gọi tập lệnh thông qua tệp lô nhưng phương pháp đó vẫn chưa thành công.

Câu trả lời:


172

Các tệp hàng loạt không phải là tệp thực thi. Họ cần một ứng dụng để chạy chúng (tức là cmd).

Trên UNIX, tệp script có shebang (#!) Ở đầu tệp để chỉ định chương trình thực thi nó. Nhấp đúp trong Windows được thực hiện bởi Windows Explorer. CreateProcesskhông biết gì về điều đó.

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

Lưu ý: Với start \"\"lệnh, một cửa sổ lệnh riêng biệt sẽ được mở với tiêu đề trống và bất kỳ đầu ra nào từ tệp lô sẽ được hiển thị ở đó. Nó cũng chỉ hoạt động với `cmd / c build.bat", trong trường hợp đó, kết quả đầu ra có thể được đọc từ tiến trình con trong Java nếu muốn.


Đối với tôi, nó nói rằng Windows không thể tìm thấy "build.bat". Vậy tôi nên đặt tập tin này ở đâu? Hay tôi nên đưa ra con đường như thế nào. Bất kỳ đề xuất?
nanospeck

1
giả sử tôi có một mảng các lệnh và sau đó lặp lại mảng đó để thực thi tất cả các lệnh for (i = 0 to command.length) {Runtime.getRuntime (). execute ("cmd / c start buil.bat"); } thì đối với mỗi lần lặp (cho mọi lệnh), một cửa sổ lệnh sẽ được mở ra, điều đó là hiển nhiên. Làm thế nào có thể tránh điều đó, tôi có nghĩa là thực hiện tất cả các lệnh trên một cửa sổ.
viveksinghggits

1
Chúng tôi có một số mã đang gọi trực tiếp "gradlew.bat" mà không đặt nội dung "cmd / c" trước nó và mã đó đang hoạt động bằng cách nào đó. Vì vậy, tôi đoán Java hoặc Windows đã khắc phục một phần của sự cố tại một số điểm. Tuy nhiên, nếu chúng tôi cố gắng thực thi "gradlew", điều đó không thành công, vì vậy rõ ràng là ".bat" vẫn cần thiết ở cuối.
Trejkaz

Win+R(Runtime) có thể thực thi trực tiếp các tệp hàng loạt.
Alex78191

21

Đôi khi thời gian xử lý luồng thực thi cao hơn thời gian xử lý luồng JVM, nó thường xảy ra khi quá trình bạn đang gọi mất một khoảng thời gian để được xử lý, hãy sử dụng lệnh waitFor () như sau:

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     

}

Bằng cách này, JVM sẽ dừng cho đến khi quá trình bạn đang gọi hoàn tất trước khi tiếp tục với ngăn xếp thực thi luồng.


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
Sẽ rất hữu ích nếu bạn nhận xét đoạn mã này và cho chúng tôi biết tại sao và dòng InputStream đang đọc, cũng như lý do tôi quan tâm. Ngoài ra, mã cho tệp loạt đang chạy tốt, nhưng tôi không thể làm cho nó gây ra lỗi Ngoại lệ.
Baruch Atta,

2
Nó sẽ khiến tôi phát điên khi có một tên biến khó hiểu như "is" trong mã của tôi.
John Fisher

14

Để chạy các tệp hàng loạt bằng java nếu bạn đang nói về ...

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

Điều này nên làm điều đó.


10
Câu hỏi đã được trả lời với một giải pháp hiệu quả. Bạn chỉ nên đưa ra các giải pháp mà bạn biết là đang hoạt động và mô tả lý do tại sao bạn cho rằng giải pháp của mình có thể tốt hơn.
Smamatti

12

ProcessBuilder là cách Java 5/6 để chạy các quy trình bên ngoài.


2
Tại sao ProcessBuilder là cách để sử dụng trong Java 5/6?
Dan Polites

2
Lựa chọn thú vị để khôi phục lại một bài đăng cũ ... ProcessBuilder cung cấp nhiều quyền kiểm soát hơn, đặc biệt là khả năng dễ dàng chuyển hướng stderr sang stdout. Tôi cũng tìm ra thiết lập trực quan hơn, nhưng đó là một pref cá nhân
basszero

10

Tệp thực thi được sử dụng để chạy tập lệnh lô cmd.exesử dụng /ccờ để chỉ định tên của tệp lô sẽ chạy:

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

Về mặt lý thuyết, bạn cũng có thể chạy Scons theo cách này, mặc dù tôi chưa thử nghiệm điều này:

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

CHỈNH SỬA: Amara, bạn nói rằng điều này không hoạt động. Lỗi bạn liệt kê là lỗi bạn gặp phải khi chạy Java từ thiết bị đầu cuối Cygwin trên hộp Windows; đây là những gì bạn đang làm? Vấn đề với điều đó là Windows và Cygwin có các đường dẫn khác nhau, vì vậy phiên bản Windows của Java sẽ không tìm thấy các scons thực thi trên đường dẫn Cygwin của bạn. Tôi có thể giải thích thêm nếu đây là vấn đề của bạn.


Cảm ơn bạn. Nó vẫn không hoạt động - đoạn mã đó thậm chí không thực thi trong ứng dụng của tôi. Tôi sẽ thử tùy chọn khác mà bạn đã trình bày. Cảm ơn một lần nữa.
Amara

Khi tôi thử giải pháp thay thế thứ hai, nó cho tôi lỗi này: Ngoại lệ trong luồng "main" java.io.IO Ngoại lệ: Không thể chạy chương trình "scons": CreateProcess error = 2, Hệ thống không thể tìm thấy tệp được chỉ định
Amara

Không, tôi không có thiết bị đầu cuối Cygwin. Tôi sử dụng Windows Command terminal. Thật kỳ lạ - tôi không biết tại sao nó không hoạt động. Nó hoàn toàn khiến tôi bối rối.
Amara

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

đã thử nghiệm với jdk1.5 và jdk1.6

Điều này đã làm việc tốt cho tôi, hy vọng nó cũng giúp những người khác. để có được điều này tôi đã phải vật lộn nhiều ngày hơn. :(


1
thêm this ==> BufferedReader reader = new BufferedReader (new InputStreamReader (p.getInputStream ())); Dòng chuỗi = reader.readLine (); while (line! = null) {System.out.println (line); line = reader.readLine (); }
Suren

2

Tôi gặp vấn đề tương tự. Tuy nhiên, đôi khi CMD không chạy được tệp của tôi. Đó là lý do tại sao tôi tạo một tệp temp.bat trên màn hình của mình, tiếp theo, tệp temp.bat này sẽ chạy tệp của tôi và tiếp theo tệp tạm thời sẽ bị xóa.

Tôi biết đây là một mã lớn hơn, tuy nhiên nó đã hoạt động với tôi 100% khi ngay cả Runtime.getRuntime (). Execute () không thành công.

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

Những điều sau đây đang hoạt động tốt:

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

/ c có nghĩa là gì?
Amal lal TL

0

Đoạn mã này sẽ thực thi hai lệnh.bat tồn tại trong đường dẫn C: / folder / folder.

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

0

Để mở rộng trên anwser của @ Isha, bạn chỉ có thể thực hiện như sau để lấy kết quả trả về (post-facto không phải trong rea-ltime) của script đã chạy:

try {
    Process process = Runtime.getRuntime().exec("cmd /c start D:\\temp\\a.bat");
    System.out.println(process.getText());
} catch(IOException e) {
    e.printStackTrace();
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.