繁体   English   中英

使用ProcessBuilder从Java调用cmd命令

[英]Invoking cmd commands from Java using 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中调用一些命令。 但是,数组元素充当上一个元素的参数。 例如,如果我使用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);
    }
   }
  1. Arrays.asList(“ cmd.exe”,“ dir”)有两个List元素。 (“ cmd.exe”,“ dir”)与(“ cmd.exe”,“ / C”,“ dir”)不同。 之所以挂起是因为您忽略了包含描述您的错误的错误消息的错误输出。 您可以使用processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);来解决此问题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。 如果这是不可接受的,则可能必须为要运行的每个命令创建一个单独的进程。

顺便说一下,StringBuffer已过时。 请改用StringBuilder,因为它没有不必要的同步开销。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM