简体   繁体   English

使用ProcessBuilder从Java调用cmd命令

[英]Invoking cmd commands from Java using processbuilder

I am trying to invoke cmd commands from Java using processbuilder. 我正在尝试使用processbuilder从Java调用cmd命令。 However I am facing few issue. 但是,我面临的问题很少。

  1. When I use List built using Arrays.asList, the application hangs infinitely after executing br.readline() (not because of loop but at readLine method). 当我使用使用Arrays.asList构建的List时,应用程序在执行br.readline()后无限期挂起(不是因为循环,而是在readLine方法中)。 Using String array gives the output. 使用String数组可提供输出。 I checked the grepcode and it looks like it should not have issue for any of these as both of them are later converted back to array when start method is invoked from processbuilder. 我检查了grepcode,看起来其中的任何一个都不应该有问题,因为当从processbuilder调用start方法时,它们都稍后会转换回数组。 (Link: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/java/lang/ProcessBuilder.java#ProcessBuilder ). (链接: http : //grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b27/java/lang/ProcessBuilder.java#ProcessBuilder )。 I am not sure what is causing this anomaly. 我不确定是什么原因导致了这种异常。

  2. This program sometimes does not give correct output. 该程序有时无法提供正确的输出。 If I use process.destroy() method and get the exitValue, it shows 1. If I comment out process.destroy() method, exception comes that process has not exited. 如果我使用process.destroy()方法并获取exitValue,则显示1。如果我注释掉process.destroy()方法,则出现异常,表明该进程尚未退出。 I guess it may be thread race condition. 我猜可能是线程竞争条件。 However, there is not effect of process.waitFor(). 但是,process.waitFor()无效。 It sometimes still produces the wrong output. 有时仍然会产生错误的输出。 How can we test these situation and find out real reason of the issue? 我们如何测试这些情况并找出问题的真正原因?

  3. I need to invoke few commands inside cmd. 我需要在cmd中调用一些命令。 However the array elements act as parameter for previous one. 但是,数组元素充当上一个元素的参数。 For example, if I make array with elemets being cmd /C dir whoami. 例如,如果我使用cmd / C dir whoami来制作元素数组。 Then this produces wrong output as whoami acts as parameter for dir. 然后这会产生错误的输出,因为whoami充当dir的参数。 What shall be the correct way to independently provide commands to cmd? 独立向cmd提供命令的正确方法是什么?

Below is the sample code having same issues: 下面是具有相同问题的示例代码:

   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") has two List elements. Arrays.asList(“ cmd.exe”,“ dir”)有两个List元素。 ("cmd.exe", "dir") is not the same as ("cmd.exe", "/C", "dir"). (“ cmd.exe”,“ dir”)与(“ cmd.exe”,“ / C”,“ dir”)不同。 It's probably hanging because you are ignoring the error output that contains the error message describing your error. 之所以挂起是因为您忽略了包含描述您的错误的错误消息的错误输出。 You can fix this with processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); 您可以使用processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);来解决此问题processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); (which is a good idea in general, unless you plan to read the error stream some other way). (通常,这是一个好主意,除非您打算以其他方式读取错误流)。
  2. Remove process.destroy() and replace process.exitValue() with process.waitFor() . 删除process.destroy()并将process.exitValue()替换为process.waitFor() Do not call process.waitFor() before you have read all of the output; 阅读所有输出之前, 请勿调用process.waitFor()。 waitFor() waits for the process to end, and you can't read output from a process that is no longer running. waitFor()等待进程结束,并且您无法从不再运行的进程中读取输出。
  3. You may be able to chain commands using && between them; 您也许可以在它们之间使用&&链接命令; for instance: new ProcessBuilder("cmd.exe", "/C", "dir && date /t") . 例如: new ProcessBuilder("cmd.exe", "/C", "dir && date /t") If that does not work, you can try creating a temporary .bat file and passing it to cmd /c. 如果这样不起作用,则可以尝试创建一个临时.bat文件,并将其传递给cmd / c。 If that isn't acceptable, you probably will have to create a separate process for each command you want to run. 如果这是不可接受的,则可能必须为要运行的每个命令创建一个单独的进程。

By the way, StringBuffer is obsolete. 顺便说一下,StringBuffer已过时。 Use StringBuilder instead, as it doesn't have the overhead of unnecessary synchronization. 请改用StringBuilder,因为它没有不必要的同步开销。

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

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