【问题标题】:Using CMD as a Process使用 CMD 作为进程
【发布时间】:2011-07-18 15:17:35
【问题描述】:

我正在尝试直接通过 Windows 上的 CMD(Linux 上的终端)运行命令。我有以下代码。它的表现非常奇怪。首先,程序运行时不打印任何内容。其次,当调试和单步执行时,程序会打印默认的 CMD 文本和输入行。最后,我似乎无法写入 CMD,所以它会执行命令。这是我的代码。我猜这可能是线程问题,但我不熟悉运行时。

    Runtime r = Runtime.getRuntime();
    try {
        Process p = r.exec("cmd");
        InputStream iStream = p.getInputStream();
        BufferedReader sReader = new BufferedReader(new InputStreamReader(iStream));
        while(sReader.ready()) {
            System.out.print((char)sReader.read());
        }

        OutputStream oStream = p.getOutputStream();
        BufferedWriter sWriter = new BufferedWriter(new OutputStreamWriter(oStream));
        sWriter.write("mkdir test");
        sWriter.newLine();

        while(sReader.ready()) {
            System.out.print((char)sReader.read());
        }
    } catch(Exception e) {
        e.printStackTrace();
    }

调试和单步执行时我的输出,(运行时不显示输出)

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

D:\workspaces\Maven\Command Line>

【问题讨论】:

  • 你使用cmd而不是直接运行每个命令有什么原因吗?
  • @unholysampler:如果打算让它在 Windows 上运行,则需要以这种方式完成(或将 cmd /c mkdir test 作为单行)。 mkdir 内置在 Windows 命令处理器中;它不是一个单独的可执行文件。当然,为什么你需要使用cmdinstead of the standard library 运行mkdir 命令是我无法理解的。
  • 我没有使用 mkdir,我只是将它用于一个简单的示例。实际的 CMD 命令又长又丑,带有动态值
  • @unholysampler - /c 正是我所需要的。为了能够将命令直接插入 CMD 并阅读它打印的内容。谢谢

标签: java process runtime cmd


【解决方案1】:

可能会发生一些事情。一是参数没有按照您执行流程的方式正确传递。另一个,就像@zacheusz 提到的那样,是输出可能来自错误流而不是输入流。

ProcessBuilder 对这两件事都有帮助,允许轻松构建命令列表以及合并输入和错误流的能力。我建议尝试使用它:

Process p = null;
try {
    List<String> cmd = new LinkedList<String>();
    cmd.add("executable");
    cmd.add("-arg1");
    cmd.add("value1");
    cmd.add("-arg2");
    ProcessBuilder pb = new ProcessBuilder(cmd);
    pb.redirectErrorStream(true);
    p = pb.start();
    BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while (input.ready()) {
        String line = input.readLine();
        System.out.println("From process: "+line);
    }
    input.close();
} catch (IOException e) {
    this.logMessage("IOException caught: "+e.getMessage());
    e.printStackTrace();
}

【讨论】:

    【解决方案2】:

    你需要在一个线程中完成这项工作。例如记录标准输出:

    Process process = Runtime.getRuntime().exec(command);
    LogStreamReader lsr = new LogStreamReader(process.getInputStream());
    Thread thread = new Thread(lsr, "LogStreamReader");
    thread.start();
    
    
    public class LogStreamReader implements Runnable {
    
        private BufferedReader reader;
    
        public LoggingStreamReader(InputStream is) {
            this.reader = new BufferedReader(new InputStreamReader(is));
        }
    
        public void run() {
            try {
                String line = reader.readLine();
                while (line != null) {
                    System.out.println(line);
                    line = reader.readLine();
                }
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    然后你需要第二个线程来处理输入。您可能希望像处理 stdout 一样处理 stderr。

    【讨论】:

      【解决方案3】:

      几年前我在网上找到了这段代码。我不记得在哪里。它已经很老了,所以现在可能会有更好的东西。

       private void executeCommand(String cmd) {
              try {
                  Runtime rt = Runtime.getRuntime();
      
                  Process proc = rt.exec(cmd);
      
                  // any error message?
                  StreamHandler errorGobbler = new StreamHandler(proc.getErrorStream(), "ERR");
      
                  // any output?
                  StreamHandler outputGobbler = new StreamHandler(proc.getInputStream(), "OUT");
      
                  // kick them off
                  errorGobbler.start();
                  outputGobbler.start();
      
                  // any error???
                  int exitVal = proc.waitFor();
                  System.out.println("ExitValue: " + exitVal);
              } catch (Exception e) {
                  e.printStackTrace();
              }
      
      
          }
      

      还有班级:

      import java.util.*;
      import java.io.*;
      
      public class StreamHandler extends Thread {
          InputStream is;
          String type;
          OutputStream os;
      
          StringBuffer output;
      
          StreamHandler(InputStream is, String type) {
              this(is, type, null);
          }
      
          StreamHandler(InputStream is, String type, OutputStream redirect) {
      
              this.is = is;
              this.type = type;
              this.os = redirect;
              output = new StringBuffer(100);
          }
      
          public void run() {
              try {
                  PrintWriter pw = null;
                  if (os != null)
                      pw = new PrintWriter(os);
      
                  InputStreamReader isr = new InputStreamReader(is);
                  BufferedReader br = new BufferedReader(isr);
                  String line=null;
                  while ( (line = br.readLine()) != null) {
                      if (pw != null)
                          pw.println(line);
                      System.out.println(type + ">" + line);
                  }
                  if (pw != null)
                      pw.flush();
              } catch (IOException ioe) {
                  ioe.printStackTrace();
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        通常cmdterminal 负责为它们执行的程序设置标准io,所以我认为您不能只通过输入/输出流与它们通信。在 Linux 的情况下,实际上是在终端内运行的 shell 执行命令,而不是终端本身。 Windows 可能也会做一些时髦的事情。

        【讨论】:

          【解决方案5】:

          您可以执行命令,而无需将 cmd.exe 硬编码到代码中。

          public static void main(String[] args) {
          
                //cmd = the command youw ill be using            
              String cmd = "ipconfig";      
              Runtime r = Runtime.getRuntime();      
              Process p;   
              try {       
                  p = r.exec(cmd);
          
              BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));    
              String inputLine;       
              while ((inputLine = in.readLine()) != null) {     
                  System.out.println(inputLine);
                    }       
              }     
          
          
          catch (IOException ex) {      
          Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);  
                       }
                 }
          

          【讨论】:

            【解决方案6】:

            cmd 尝试运行命令提示符,

            要正确运行命令,您需要以下命令行

            cmd.exe -c ipconfig.exe

            -c 表示在命令行的其余部分运行命令

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-11-24
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多