使用processbuilder从Java调用cmd命令

时间:2017-04-21 19:01:11

标签: java processbuilder

我正在尝试使用processbuilder从Java调用cmd命令。但是我面临的问题很少。

  1. 当我使用使用Arrays.asList构建的List时,应用程序在执行br.readline()后无限地挂起(不是因为循环而是在readLine方法)。使用String数组给出输出。我检查了grepcode,它看起来应该没有任何问题,因为当从processbuilder调用start方法时,它们都会被转换回数组。 (链接:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/java/lang/ProcessBuilder.java#ProcessBuilder)。我不确定是什么导致了这种异常现象。

  2. 此程序有时无法提供正确的输出。如果我使用process.destroy()方法并获取exitValue,则显示1.如果我注释掉process.destroy()方法,那么异常将导致该进程未退出。我想这可能是线程竞争条件。但是,process.waitFor()没有效果。它有时仍会产生错误的输出。我们如何测试这些情况并找出问题的真正原因?

  3. 我需要在cmd中调用一些命令。但是,数组元素充当前一个的参数。例如,如果我使用elemets制作数组cmd / C dir whoami。然后这会产生错误的输出,因为whoami充当dir的参数。什么是向cmd独立提供命令的正确方法?

  4. 以下是具有相同问题的示例代码:

       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);
        }
       }
    

1 个答案:

答案 0 :(得分:2)

  1. Arrays.asList(“cmd.exe”,“dir”)有两个List元素。 (“cmd.exe”,“dir”)与(“cmd.exe”,“/ C”,“dir”)不同。它可能会挂起,因为您忽略了包含描述错误的错误消息的错误输出。您可以使用processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);解决这个问题(一般来说这是一个好主意,除非您打算以其他方式读取错误流)。
  2. 删除process.destroy()并将process.exitValue()替换为process.waitFor()在读完所有输出之前,不要调用process.waitFor(); waitFor()等待进程结束,并且您无法读取不再运行的进程的输出。
  3. 您可以在它们之间使用&&链接命令;例如:new ProcessBuilder("cmd.exe", "/C", "dir && date /t")。如果这不起作用,您可以尝试创建临时.bat文件并将其传递给cmd / c。如果这是不可接受的,您可能必须为要运行的每个命令创建一个单独的进程。
  4. 顺便说一句,StringBuffer已经过时了。请改用StringBuilder,因为它没有不必要的同步开销。