ฉันจะรันไฟล์แบตช์จาก Java Application ได้อย่างไร?


107

ในแอปพลิเคชัน Java ของฉันฉันต้องการเรียกใช้ไฟล์แบตช์ที่เรียก " scons -Q implicit-deps-changed build\file_load_type export\file_load_type"

ดูเหมือนว่าฉันจะไม่สามารถเรียกใช้ไฟล์แบตช์ได้ด้วยซ้ำ ฉันหมดความคิด

นี่คือสิ่งที่ฉันมีใน Java:

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

ก่อนหน้านี้ฉันมีไฟล์ Python Sconscript ที่ฉันต้องการเรียกใช้ แต่เนื่องจากไม่ได้ผลฉันจึงตัดสินใจเรียกสคริปต์ผ่านไฟล์แบตช์ แต่วิธีนั้นยังไม่ประสบความสำเร็จ

คำตอบ:


172

ไฟล์แบตช์ไม่ใช่ไฟล์ปฏิบัติการ พวกเขาต้องการแอปพลิเคชันเพื่อเรียกใช้งาน (เช่น cmd)

ใน UNIX ไฟล์สคริปต์จะมี shebang (#!) ที่จุดเริ่มต้นของไฟล์เพื่อระบุโปรแกรมที่เรียกใช้งาน การดับเบิลคลิกใน Windows ดำเนินการโดย Windows Explorer CreateProcessไม่รู้อะไรเลย

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

หมายเหตุ: ด้วยstart \"\"คำสั่งหน้าต่างคำสั่งแยกต่างหากจะถูกเปิดขึ้นพร้อมกับหัวเรื่องที่ว่างเปล่าและเอาต์พุตใด ๆ จากไฟล์แบตช์จะแสดงที่นั่น นอกจากนี้ควรใช้งานได้กับเพียงแค่ `cmd / c build.bat” ซึ่งในกรณีนี้สามารถอ่านเอาต์พุตจากกระบวนการย่อยใน Java ได้หากต้องการ


สำหรับฉันมันบอกว่า Windows ไม่พบ "build.bat" ฉันควรวางไฟล์นี้ไว้ที่ไหน? หรือควรให้ทางอย่างไร. ข้อเสนอแนะใด ๆ ?
nanospeck

1
สมมติว่าฉันมีอาร์เรย์ของคำสั่งแล้ววนซ้ำอาร์เรย์นั้นเพื่อดำเนินการคำสั่งทั้งหมดสำหรับ (i = 0 ถึง commands.length) {Runtime.getRuntime (). exec ("cmd / c start buil.bat"); } จากนั้นสำหรับการทำซ้ำทุกครั้ง (สำหรับทุกคำสั่ง) หน้าต่างคำสั่งจะเปิดขึ้นซึ่งเห็นได้ชัด จะหลีกเลี่ยงได้อย่างไรว่าฉันหมายถึงการดำเนินการคำสั่งทั้งหมดในหน้าต่างเดียว
viveksinghggits

1
เรามีโค้ดบางตัวที่เรียกว่า "gradlew.bat" โดยตรงโดยไม่ต้องใส่ "cmd / c" ไว้ข้างหน้าและโค้ดนั้นก็ใช้งานได้ ดังนั้นฉันเดาว่า Java หรือ Windows คงเป็นส่วนหนึ่งของปัญหาในบางจุด ถ้าเราพยายาม exec "gradlew" มันก็ล้มเหลวดังนั้นเห็นได้ชัดว่า ".bat" ยังคงเป็นสิ่งที่จำเป็นในตอนท้าย
Trejkaz

Win+R(Runtime) สามารถรันไฟล์แบตช์ได้โดยตรง
Alex78191

21

บางครั้งเวลาดำเนินการเธรดจะสูงกว่าเวลารอดำเนินการเธรด JVM ซึ่งจะเกิดขึ้นเมื่อกระบวนการที่คุณเรียกใช้ใช้เวลาในการประมวลผลใช้คำสั่ง waitFor () ดังต่อไปนี้:

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     

}

ด้วยวิธีนี้ JVM จะหยุดจนกว่ากระบวนการที่คุณเรียกใช้จะเสร็จสิ้นก่อนที่จะดำเนินการต่อด้วยสแต็กการเรียกใช้เธรด


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
การแสดงความคิดเห็นเกี่ยวกับรหัสนี้จะเป็นประโยชน์และบอกเราว่าทำไมและสิ่งที่ InputStream กำลังอ่านอยู่และทำไมฉันถึงสนใจ นอกจากนี้รหัสสำหรับไฟล์แบตช์ยังทำงานได้ดี แต่ฉันไม่สามารถทำให้มันเพิ่มข้อผิดพลาดได้
Baruch Atta

2
มันจะกระตุ้นให้ฉันมีชื่อตัวแปรที่น่าสับสนเช่น "is" ในรหัสของฉัน
John Fisher

14

ในการรันไฟล์แบตช์โดยใช้ java หากคุณกำลังพูดถึง ...

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

สิ่งนี้ควรทำ


10
คำถามได้รับคำตอบแล้วพร้อมวิธีแก้ปัญหาที่ใช้งานได้ คุณควรเสนอเฉพาะโซลูชันที่คุณรู้ว่าใช้งานได้และอธิบายเหตุผลที่คุณคิดว่าโซลูชันของคุณน่าจะดีกว่า
Smamatti

12

ProcessBuilderเป็นวิธี Java 5/6 ในการรันกระบวนการภายนอก


2
เหตุใด ProcessBuilder จึงเป็นวิธีที่จะไปใน Java 5/6
Dan Polites

2
ทางเลือกที่น่าสนใจในการรื้อฟื้นโพสต์เก่า ... ProcessBuilder ให้การควบคุมที่มากขึ้นโดยเฉพาะความสามารถในการเปลี่ยนเส้นทาง stderr ไปยัง stdout ได้อย่างง่ายดาย ฉันยังพบว่าการตั้งค่านั้นใช้งานง่ายกว่า แต่นั่นเป็นการตั้งค่าส่วนบุคคล
basszero

10

ไฟล์ปฏิบัติการที่ใช้ในการรันสคริปต์แบตช์คือcmd.exeสิ่งที่ใช้/cแฟล็กเพื่อระบุชื่อของไฟล์แบตช์ที่จะรัน:

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

ในทางทฤษฎีคุณควรจะสามารถเรียกใช้ Scons ในลักษณะนี้ได้แม้ว่าฉันจะไม่ได้ทดสอบสิ่งนี้:

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

แก้ไข: อมราคุณบอกว่ามันใช้ไม่ได้ ข้อผิดพลาดที่คุณระบุเป็นข้อผิดพลาดที่คุณได้รับเมื่อเรียกใช้ Java จากเทอร์มินัล Cygwin บนกล่อง Windows นี่คุณกำลังทำอะไรอยู่? ปัญหาคือ Windows และ Cygwin มีเส้นทางที่แตกต่างกันดังนั้น Java เวอร์ชัน Windows จะไม่พบ scons ที่ทำงานได้บนเส้นทาง Cygwin ของคุณ ฉันสามารถอธิบายเพิ่มเติมได้หากสิ่งนี้กลายเป็นปัญหาของคุณ


ขอบคุณ. มันยังใช้ไม่ได้ - ส่วนของโค้ดนั้นไม่ทำงานในแอพของฉันด้วยซ้ำ ฉันจะลองตัวเลือกอื่นที่คุณนำเสนอ ขอบคุณอีกครั้ง.
อมรา

เมื่อฉันลองทางเลือกที่สองมันทำให้ฉันเกิดข้อผิดพลาดนี้: ข้อยกเว้นในเธรด "main" java.io.IOException: ไม่สามารถรันโปรแกรม "scons": ข้อผิดพลาด CreateProcess = 2 ระบบไม่พบไฟล์ที่ระบุ
Amara

ไม่ฉันไม่มีเทอร์มินัล Cygwin ฉันใช้ Windows Command Terminal มันแปลก - ฉันไม่รู้ว่าทำไมมันถึงใช้ไม่ได้ มันทำให้ฉันงงงวยไปหมด
อมรา

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

ทดสอบด้วย jdk1.5 และ jdk1.6

สิ่งนี้ใช้ได้ดีสำหรับฉันหวังว่ามันจะช่วยคนอื่น ๆ ด้วย เพื่อให้ได้สิ่งนี้ฉันต้องดิ้นรนมากขึ้นหลายวัน :(


1
เพิ่มสิ่งนี้ ==> ผู้อ่าน BufferedReader = BufferedReader ใหม่ (ใหม่ InputStreamReader (p.getInputStream ())); สายอักขระ = reader.readLine (); ในขณะที่ (line! = null) {System.out.println (line); บรรทัด = reader.readLine (); }
สุเรน

2

ฉันมีปัญหาเดียวกัน อย่างไรก็ตามบางครั้ง CMD ไม่สามารถเรียกใช้ไฟล์ของฉันได้ นั่นเป็นเหตุผลที่ฉันสร้าง temp.bat บนเดสก์ท็อปของฉันถัดไป temp.bat นี้จะเรียกใช้ไฟล์ของฉันและไฟล์ temp ถัดไปจะถูกลบ

ฉันรู้ว่านี่เป็นรหัสที่ใหญ่กว่า แต่ใช้ได้กับฉัน 100% แม้ Runtime.getRuntime (). exec () ล้มเหลว

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

สิ่งต่อไปนี้ใช้งานได้ดี:

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

/ c หมายถึงอะไร?
Amal lal TL

0

รหัสนี้จะรันคำสั่งสองคำสั่ง bat ที่มีอยู่ในพา ธ C: / โฟลเดอร์ / โฟลเดอร์

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

0

หากต้องการขยายในanwser ของ @ Ishaคุณสามารถทำสิ่งต่อไปนี้เพื่อรับเอาต์พุตที่ส่งคืน (post-facto ไม่อยู่ใน rea-ltime) ของสคริปต์ที่รัน:

try {
    Process process = Runtime.getRuntime().exec("cmd /c start D:\\temp\\a.bat");
    System.out.println(process.getText());
} catch(IOException e) {
    e.printStackTrace();
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.