gpt4 book ai didi

java - 执行显示控制台窗口的命令并获取进程的句柄

转载 作者:搜寻专家 更新时间:2023-10-31 20:08:38 25 4
gpt4 key购买 nike

我正在尝试从 Java 运行一个命令,该命令将启动一个运行几分钟的进程。我只需要触发命令并获取进程句柄并继续循环中的其他操作。每隔一段时间,我将不得不监视进程是否仍然处于 Activity 状态。

我还需要显示控制台窗口,以便为用户显示流程的输出。

目前,我尝试了 Runtime 和 ProcessBuilder 类的方法来运行我的命令,但它们都没有帮助我实现我的目标。

示例代码:

//Changing the directory and running Maven exec: java command on the POM file in that directory.

String cmd = "cd C:/Test & mvn exec:java";
String finalCmd = "cmd /c \""+ cmd +"\"";

Process process = Runtime.getRuntime().exec(finalCmd);
Thread.sleep(10);
boolean alive = process.isAlive();

变量 alive 的值为 True,但我没有看到进程启动。当程序执行完成后,进程才会开始,我不确定为什么会这样。

还要显示控制台窗口,我从谷歌发现我需要使用以下命令:

String finalCmd = "cmd /c start cmd.exe /c \"" + cmd + "\"";

然而,有了这个,进程会立即启动,但我没有得到进程句柄,因为我发现 alive 变量显示 false。

有人知道如何实现这个目标吗?如果无法同时执行这两项操作,我没意见,但至少我需要启动流程执行并获取句柄以在我的代码中稍后监控流程状态。

最佳答案

这里发生了一些不正确的事情:

  • 我们需要将我们的命令作为字符串标记传递给 exec() 命令
  • 我们需要使用 process.waitFor() 等待进程退出,而不是 hibernate ,这将阻塞当前线程,因此如果您不想在另一个线程中执行它或使用 ExecutorService。
  • 建议检查 waitFor() 的输出值以查看我们的命令是否正确执行(值为 0)或不正确(任何其他值,如果执行不成功,通常为正 1)
  • 可选地(为了查看输出)我们需要将标准 OUT 和 ERR 重定向到某个地方,比如将其打印到控制台(),尽管您可以将其放入某个 GUI 窗口等的文件中。

因此至少以下代码应该可以工作:

Process process = Runtime.getRuntime().exec(new String[] {"cmd", "/c", "cd", "C:\\dev", "&&", "dir"});
int outputVal = process.waitFor();
boolean alive = process.isAlive();
System.out.format("alive %s, outputVal: %d\n",alive, outputVal);

进一步的建议:

  • 使用 ProcessBuilder 而不是 runTime.exec(),它允许更多控制并且是自 JDK 1.5 以来推荐的方式
  • 读取输入流

所以代码看起来像这样:

    List<String> cmdList = Arrays.asList("cmd", "/c", "cd", "C:\\dev", "&&", "dir");
ProcessBuilder pb = new ProcessBuilder(cmdList);
pb.redirectErrorStream(true); //redirect STD ERR to STD OUT
Process process = pb.start();
try (final BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line = null;
while ((line = br.readLine()) != null) {
System.out.println("std-out-line: " + line);
}
}
int outputVal = process.waitFor();
System.out.format("outputVal: %d\n", outputVal);

由于 waitFor() 是一个阻塞调用,您可以在单独的线程中或使用 executorService 执行它。此处示例代码:

    final StringBuffer outputSb = new StringBuffer();
ExecutorService executorService = null;
try {
executorService = Executors.newSingleThreadExecutor();
final Future<Integer> future = executorService.submit(new Callable<Integer>() {

@Override
public Integer call() throws Exception {
try (final BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
String line = null;
while ((line = br.readLine()) != null) {
outputSb.append("std-out-line: ");
outputSb.append(line);
outputSb.append('\n');
}
}
int exitValue = process.waitFor();
System.out.format("exitValue: %d\n", exitValue);

return exitValue;
}
});

while (!future.isDone()) {
System.out.println("Waiting for command to finish doing something else..");
Thread.sleep(1 * 1000);
}

int exitValue = future.get();
System.out.println("Output: " + outputSb);

} finally {
executorService.shutdown();
}

关于java - 执行显示控制台窗口的命令并获取进程的句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48766140/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com