Java 調用 Runtime.exec("cmd /c script.bat") 會彈出黑框窗口,體驗極差,尤其在 GUI 程式或服務中不可接受。
import java.io.*;
public class SilentBatExecutor {
public static void execute(String batPath) throws IOException {
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", batPath);
// 關鍵:合併錯誤流到標準流,並重定向到文件或丟棄
pb.redirectErrorStream(true);
pb.redirectOutput(ProcessBuilder.Redirect.to(new File("bat.log"))); // 或 Redirect.DISCARD
Process process = pb.start();
try {
int exitCode = process.waitFor();
System.out.println("批處理退出碼: " + exitCode);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("執行被中斷", e);
}
}
public static void main(String[] args) throws IOException {
execute("D:/scripts/backup.bat");
}
}
| 設置 | 作用 |
|---|---|
cmd.exe /c | 執行命令後退出 |
redirectErrorStream(true) | 合併 stderr 到 stdout,單一流處理 |
redirectOutput(Redirect.to(file)) | 輸出寫入日誌文件,便於事後排查 |
redirectOutput(Redirect.DISCARD) | 直接丟棄輸出(不需要日誌時) |
pb.directory(workDir) | 指定批處理工作目錄(相對路徑依賴此項) |
若不重定向到文件,必須啟動獨立線程消費 stdout/stderr,否則管道滿導致子進程掛起:
Process process = pb.start();
new Thread(() -> {
try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) log.info(line);
} catch (IOException ignored) {}
}).start();
process.waitFor();
javaw.exe 啟動主程式(無控制台)pause、echo 等交互命令requireAdministrator 或使用任務計劃程式Runtime.getRuntime().exec("script.bat") 直接調用 → 依賴文件關聯,不可控且仍彈窗waitFor() 永不返回"D:/Program Files/script.bat"