我不确定如何通过 Java 代码启动外部应用程序(特别是在 Windows 上)。我不打算在 Mac/Linux 上使用这个 Java 代码,所以让我们重点关注 Windows 代码。
我这两天研究这个问题,还是没有找到答案。我轻松找到了
Runtime.getRuntime().exec()
方法,但问题是我找不到有关 从 IntelliJ Idea 中的本地工作区启动批处理 (.bat) 文件的信息。
我只是想知道如何在我的工作区中执行本地批处理文件(在像
com.example.batch
这样的文件夹中)和/或如何使用直接文件地址执行(.exe)或(.bat)。 (例如适用于 Windows 的碎片整理和优化驱动器 (.exe):C:\WINDOWS\system32\dfrgui.exe
)
提前感谢大家,我一直渴望得到这个答案。
首先,您应该使用
ProcessBuilder
来执行外部程序,以获得比 Runtime.getRuntime().exec()
更易于使用的界面。
其次,要执行
.bat
文件,您所要做的就是执行cmd.exe
并在/C
选项中传递批处理文件名。 请注意,当您运行批处理文件时,您正在启动 DOS cmd 处理器并告诉它运行批处理文件而不是从终端读取。 因此,批处理文件必须位于 cmd.exe
可以访问的位置。 因此它不能位于包含 Java 程序的 jar 文件内。 如果需要将其分发到 jar 中,则必须将其复制到文件系统的某个位置。
您读过重要的 Runtime.exec() 文章吗?
本文第 2 页列出了一个常见陷阱:Runtime.exec() 不是命令行。
.bat 文件不是可执行文件。它们是指令的集合。就像 Linux 中的 shell 脚本一样,您需要一些东西来实际执行这些指令。
在本例中,您的可执行文件是
cmd.exe
,它将采用 /C
和 com.example.batch
作为其参数:
Runtime.getRuntime().exec(new String[] { "cmd.exe", "/C", "com.example.batch"});
顺便说一句,请查看
ProcessBuilder
课程。比Runtime
好多了。是的,Runtime
文章中的所有规则都适用于ProcessBuilder
。
公共类RestartBat {
public static void main(String[] args) throws IOException, InterruptedException {
int port = 8892;
if (available(port)) {
System.out.println("Active");
getProcessesOnPort(String.valueOf(port)).stream().forEach(p -> killProcess(p));
} else {
System.out.println("Non Active");
runningBat();
}
}
// get all processes on a specific port
private static Set<String> getProcessesOnPort(String port) {
Set<String> processesOnPort = new HashSet<String>();
Process process;
String out = "";
try {
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", "netstat -ano | findstr :" + port);
process = pb.start();
process.waitFor();
int bytesRead = -1;
byte[] bytes = new byte[1024];
while ((bytesRead = process.getInputStream().read(bytes)) > -1) {
out = out + new String(bytes, 0, bytesRead);
}
} catch (IOException e) {
System.out.println("Error while finding processes for port " + port);
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("Error while finding processes for port " + port);
e.printStackTrace();
}
Pattern pattern = Pattern.compile("([0-9]{1,5}$)");
Matcher matcher = pattern.matcher(out);
while (matcher.find()) {
processesOnPort.add(matcher.group(1));
}
return processesOnPort;
}
// kill process using its ID
private static void killProcess(String processID) {
System.out.println("Killing process with ID " + processID + "...");
String cmd = "taskkill /F /PID " + processID;
try {
Runtime.getRuntime().exec(cmd);
System.out.println("Success Killied " + processID + "!");
//runningBat();
} catch (IOException e) {
System.out.println("Could not kill process with ID " + processID);
e.printStackTrace();
}
}
private static void runningBat() {
String url = "C:/API Services/snap-bi-bca/start-bi-snap.bat";
try {
String[] command = {"cmd.exe", "/C", "Start", new File(url).toURI().toString()};
Process p = Runtime.getRuntime().exec(command, null, new File(url).getParentFile());
} catch (IOException ex) {
System.out.println(ex);
}
}
public static boolean available(int port) {
System.out.println("--------------Testing port " + port);
Socket s = null;
try {
s = new Socket("localhost", port);
// If the code makes it this far without an exception it means
// something is using the port and has responded.
//System.out.println("--------------Port " + port + " is not available");
return true;
} catch (IOException e) {
//System.out.println("--------------Port " + port + " is available");
return false;
} finally {
if (s != null) {
try {
s.close();
} catch (IOException e) {
throw new RuntimeException("You should handle this error.", e);
}
}
}
}