【问题标题】:How to execute cmd commands via Java如何通过Java执行cmd命令
【发布时间】:2011-05-08 14:57:33
【问题描述】:

我正在尝试通过 Java 执行命令行参数。例如:

// Execute command
String command = "cmd /c start cmd.exe";
Process child = Runtime.getRuntime().exec(command);

// Get output stream to write from it
OutputStream out = child.getOutputStream();

out.write("cd C:/ /r/n".getBytes());
out.flush();
out.write("dir /r/n".getBytes());
out.close();

上面打开命令行但不执行cddir。有任何想法吗?我正在运行 Windows XP、JRE6。

(我已将我的问题修改得更具体。以下答案很有帮助,但不回答我的问题。)

【问题讨论】:

  • joe,如果您仍然觉得您的问题没有得到解答,我认为您应该提供更多背景信息。我的回答肯定能达到你想要达到的目的,即列出 C:\ 中的文件。 Vincent 和 Carles 的回答向您展示了如何通过单个 exec() 调用运行多个 shell 命令。我不确定您目前对什么不满意。

标签: java exec


【解决方案1】:

我在 forums.oracle.com 上找到了这个

允许重用一个进程在 Windows 中执行多个命令:http://kr.forums.oracle.com/forums/thread.jspa?messageID=9250051

你需要类似的东西

   String[] command =
    {
        "cmd",
    };
    Process p = Runtime.getRuntime().exec(command);
    new Thread(new SyncPipe(p.getErrorStream(), System.err)).start();
    new Thread(new SyncPipe(p.getInputStream(), System.out)).start();
    PrintWriter stdin = new PrintWriter(p.getOutputStream());
    stdin.println("dir c:\\ /A /Q");
    // write any other commands you want here
    stdin.close();
    int returnCode = p.waitFor();
    System.out.println("Return code = " + returnCode);

SyncPipe 类:

class SyncPipe implements Runnable
{
public SyncPipe(InputStream istrm, OutputStream ostrm) {
      istrm_ = istrm;
      ostrm_ = ostrm;
  }
  public void run() {
      try
      {
          final byte[] buffer = new byte[1024];
          for (int length = 0; (length = istrm_.read(buffer)) != -1; )
          {
              ostrm_.write(buffer, 0, length);
          }
      }
      catch (Exception e)
      {
          e.printStackTrace();
      }
  }
  private final OutputStream ostrm_;
  private final InputStream istrm_;
}

【讨论】:

  • 很好,链接无效,但这里复制的代码就足够了。
  • @tvanfosson 嗨,我有一个疑问!它适用于“cmd”,我无法将其用于“powershell”。有什么我可以遵循的解决方法吗?
【解决方案2】:

如果你想在 cmd shell 中运行多个命令,那么你可以像这样构造一个命令:

  rt.exec("cmd /c start cmd.exe /K \"cd c:/ && dir\"");

This page 解释更多。

【讨论】:

    【解决方案3】:

    exec 的每次执行都会产生一个具有自己环境的新进程。因此,您的第二次调用与第一次调用没有任何关联。它只会更改它自己的工作目录然后退出(即它实际上是一个无操作)。

    如果您想编写请求,您需要在一次调用 exec 中完成此操作。如果多个命令用分号分隔,Bash 允许在一行中指定多个命令; Windows CMD 可能允许同样的操作,如果不允许,总是有批处理脚本。

    As Piotr says,如果此示例实际上正是您想要实现的目标,您可以通过以下方式更高效、更有效且平台安全地执行相同的操作:

    String[] filenames = new java.io.File("C:/").list();
    

    【讨论】:

    • @Boris - 检查问题历史记录,自从我发布此答案以来,已在两个月内对其进行了编辑。
    【解决方案4】:

    您发布的代码启动了三个不同的进程,每个进程都有自己的命令。要打开命令提示符然后运行命令,请尝试以下操作(我自己从未尝试过):

    try {
        // Execute command
        String command = "cmd /c start cmd.exe";
        Process child = Runtime.getRuntime().exec(command);
    
        // Get output stream to write from it
        OutputStream out = child.getOutputStream();
    
        out.write("cd C:/ /r/n".getBytes());
        out.flush();
        out.write("dir /r/n".getBytes());
        out.close();
    } catch (IOException e) {
    }
    

    【讨论】:

    • 谢谢。这会打开命令行,但不会执行 cd 或 dir 命令。
    • 天啊,我喜欢带有免责声明的代码 sn-ps:“我自己从未尝试过。” >_
    • 这样打开命令行,却没有执行cd或dir命令,为什么?
    • 为什么它被批准了......它的误报!
    • 下面的答案有实际答案。
    【解决方案5】:

    试试这个link

    您不使用“cd”来更改运行命令的目录。您需要要运行的可执行文件的完整路径。

    此外,使用文件/目录类更容易列出目录的内容

    【讨论】:

    • 答案与问题无关
    【解决方案6】:

    您的每个 exec 调用都会创建一个进程。您的第二个和第三个调用不在您在第一个中创建的同一个 shell 进程中运行。尝试将所有命令放在一个 bat 脚本中并在一次调用中运行它: rt.exec("cmd myfile.bat"); 或类似

    【讨论】:

    • 答案与问题的代码无关 - 没有“其他”执行调用
    • 我回复的时候有过,但是问题已经被编辑过了。请在投票前查看此问题的修订历史记录。
    【解决方案7】:

    这是因为每个 runtime.exec(..) 返回一个 Process 类,应该在执行后使用,而不是通过 Runtime 类调用其他命令

    如果你查看Process doc,你会发现你可以使用

    • getInputStream()
    • getOutputStream()

    您应该通过发送连续的命令并检索输出来工作..

    【讨论】:

      【解决方案8】:

      从进程写入输出流是错误的方向。在这种情况下,“出”意味着从流程到您。尝试获取/写入进程的输入流并从输出流中读取以查看结果。

      【讨论】:

        【解决方案9】:

        因为我也遇到了同样的问题,并且因为这里的一些人评论说该解决方案对他们不起作用,所以这里是找到有效解决方案的帖子的链接。

        https://*.com/a/24406721/3751590

        另请参阅使用 Cygwin 终端的最佳答案中的“更新”

        【讨论】:

          【解决方案10】:
          try {
              String command = "Command here";
              Runtime.getRuntime().exec("cmd /c start cmd.exe /K " + command);
          } catch (IOException e) {
              e.printStackTrace();
          }
          

          【讨论】:

          • 请在您的答案中添加一些解释,以便其他人可以从中学习
          【解决方案11】:

          这是一个不需要多线程的简单示例:

          import java.io.IOException;
          import java.io.InputStream;
          import java.io.OutputStream;
          
          public class SimplePty
          {
              public SimplePty(Process process) throws IOException
              {
                  while (process.isAlive())
                  {
                      sync(process.getErrorStream(), System.err);
                      sync(process.getInputStream(), System.out);
                      sync(System.in, process.getOutputStream());
                  }
              }
              
              private void sync(InputStream in, OutputStream out) throws IOException
              {
                  while (in.available() > 0)
                  {
                      out.write(in.read());
                      out.flush();
                  }
              }
              
              public static void main( String[] args ) throws IOException
              {
                  String os = System.getProperty("os.name").toLowerCase();
                  String shell = os.contains("win") ? "cmd" : "bash";
                  Process process = new ProcessBuilder(shell).start();
                  new SimplePty(process);
              }
          }
          

          【讨论】: