使用 processbuilder 从 Java 调用 cmd 命令
Invoking cmd commands from Java using processbuilder
我正在尝试使用 processbuilder 从 Java 调用 cmd 命令。但是我面临的问题很少。
当我使用使用 Arrays.asList 构建的列表时,应用程序在执行 br.readline() 后无限挂起(不是因为循环而是在 readLine 方法)。使用 String 数组给出输出。我检查了 grepcode,它看起来应该没有任何问题,因为当从 processbuilder 调用 start 方法时,它们稍后都转换回数组。 (Link:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/java/lang/ProcessBuilder.java#ProcessBuilder)。我不确定是什么导致了这种异常。
这个程序有时不能给出正确的输出。如果我使用 process.destroy() 方法并获取 exitValue,它显示 1。如果我注释掉 process.destroy() 方法,则会出现异常,进程尚未退出。我想这可能是线程竞争条件。但是,process.waitFor() 没有效果。它有时仍然会产生错误的输出。我们如何测试这些情况并找出问题的真正原因?
我需要在 cmd 中调用几个命令。然而,数组元素充当前一个的参数。例如,如果我创建数组,元素为 cmd /C dir whoami。然后这会产生错误的输出,因为 whoami 充当 dir 的参数。独立向cmd提供命令的正确方法是什么?
下面是具有相同问题的示例代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
public class Sample {
public static void main(String[] args) throws Exception {
//List<String> commandList = Arrays.asList("cmd.exe","dir");
String[] commandList = {"cmd.exe", "/C", "dir"};
//String[] commandList = {"cmd.exe", "/C", "dir", "whoami"};
//String[] commandList = new String[] {"cmd.exe", "/C", "dir"};
ProcessBuilder processBuilder = new ProcessBuilder(commandList);
Process process = processBuilder.start();
//process.waitFor();
BufferedReader iReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String tempStr= "";
StringBuffer buffer = new StringBuffer();
while((tempStr = iReader.readLine())!=null){
buffer.append(tempStr+System.lineSeparator());
}
System.out.println(buffer.toString());
process.destroy();
int exitValue = process.exitValue();
System.out.println(exitValue);
}
}
- Arrays.asList("cmd.exe","dir") 有两个列表元素。 ("cmd.exe", "dir") 与 ("cmd.exe", "/C", "dir") 不同。它可能挂起,因为您忽略了包含描述错误的错误消息的错误输出。您可以使用
processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
解决此问题(通常这是个好主意,除非您打算以其他方式读取错误流)。
- 删除 process.destroy() 并将 process.exitValue() 替换为
process.waitFor()
。 在阅读所有输出之前,不要调用process.waitFor(); waitFor() 等待进程结束,您无法读取不再 运行ning. 的进程的输出
- 您可以在它们之间使用
&&
链接命令;例如:new ProcessBuilder("cmd.exe", "/C", "dir && date /t")
。如果这不起作用,您可以尝试创建一个临时 .bat 文件并将其传递给 cmd /c。如果这是不可接受的,您可能必须为每个要执行的命令创建一个单独的进程 运行.
顺便说一下,StringBuffer 已经过时了。请改用 StringBuilder,因为它没有不必要的同步开销。
我正在尝试使用 processbuilder 从 Java 调用 cmd 命令。但是我面临的问题很少。
当我使用使用 Arrays.asList 构建的列表时,应用程序在执行 br.readline() 后无限挂起(不是因为循环而是在 readLine 方法)。使用 String 数组给出输出。我检查了 grepcode,它看起来应该没有任何问题,因为当从 processbuilder 调用 start 方法时,它们稍后都转换回数组。 (Link:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/java/lang/ProcessBuilder.java#ProcessBuilder)。我不确定是什么导致了这种异常。
这个程序有时不能给出正确的输出。如果我使用 process.destroy() 方法并获取 exitValue,它显示 1。如果我注释掉 process.destroy() 方法,则会出现异常,进程尚未退出。我想这可能是线程竞争条件。但是,process.waitFor() 没有效果。它有时仍然会产生错误的输出。我们如何测试这些情况并找出问题的真正原因?
我需要在 cmd 中调用几个命令。然而,数组元素充当前一个的参数。例如,如果我创建数组,元素为 cmd /C dir whoami。然后这会产生错误的输出,因为 whoami 充当 dir 的参数。独立向cmd提供命令的正确方法是什么?
下面是具有相同问题的示例代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
public class Sample {
public static void main(String[] args) throws Exception {
//List<String> commandList = Arrays.asList("cmd.exe","dir");
String[] commandList = {"cmd.exe", "/C", "dir"};
//String[] commandList = {"cmd.exe", "/C", "dir", "whoami"};
//String[] commandList = new String[] {"cmd.exe", "/C", "dir"};
ProcessBuilder processBuilder = new ProcessBuilder(commandList);
Process process = processBuilder.start();
//process.waitFor();
BufferedReader iReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String tempStr= "";
StringBuffer buffer = new StringBuffer();
while((tempStr = iReader.readLine())!=null){
buffer.append(tempStr+System.lineSeparator());
}
System.out.println(buffer.toString());
process.destroy();
int exitValue = process.exitValue();
System.out.println(exitValue);
}
}
- Arrays.asList("cmd.exe","dir") 有两个列表元素。 ("cmd.exe", "dir") 与 ("cmd.exe", "/C", "dir") 不同。它可能挂起,因为您忽略了包含描述错误的错误消息的错误输出。您可以使用
processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
解决此问题(通常这是个好主意,除非您打算以其他方式读取错误流)。 - 删除 process.destroy() 并将 process.exitValue() 替换为
process.waitFor()
。 在阅读所有输出之前,不要调用process.waitFor(); waitFor() 等待进程结束,您无法读取不再 运行ning. 的进程的输出
- 您可以在它们之间使用
&&
链接命令;例如:new ProcessBuilder("cmd.exe", "/C", "dir && date /t")
。如果这不起作用,您可以尝试创建一个临时 .bat 文件并将其传递给 cmd /c。如果这是不可接受的,您可能必须为每个要执行的命令创建一个单独的进程 运行.
顺便说一下,StringBuffer 已经过时了。请改用 StringBuilder,因为它没有不必要的同步开销。