Как выполнять команды cmd через Java - PullRequest
39 голосов
/ 11 ноября 2010

Я пытаюсь выполнить аргументы командной строки через 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();

Вышеприведенное открывает командную строку, но не выполняет cd или dir. Есть идеи? Я использую Windows XP, JRE6.

(Я изменил свой вопрос, чтобы он был более конкретным. Следующие ответы были полезны, но не отвечали на мой вопрос.)

Ответы [ 9 ]

63 голосов
/ 25 марта 2011

Я нашел это на 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:

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_;
}
15 голосов
/ 11 ноября 2010

Если вы хотите выполнить несколько команд в оболочке cmd, вы можете создать одну команду, например:

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

Эта страница объясняет больше.

3 голосов
/ 11 ноября 2010

Код, который вы разместили, запускает три разных процесса, каждый со своей командой. Чтобы открыть командную строку и затем запустить команду, попробуйте следующее (сам никогда не пробовал):

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) {
}
3 голосов
/ 11 ноября 2010

Каждое выполнение exec порождает новый процесс с собственной средой. Таким образом, ваш второй вызов никак не связан с первым. Он просто изменит свой собственный рабочий каталог, а затем завершит работу (т. Е. Фактически не работает).

Если вы хотите составить запрос, вам нужно сделать это в течение одного вызова exec. Bash позволяет указывать несколько команд в одной строке, если они разделены точкой с запятой; Windows CMD может разрешать то же самое, и если нет, то всегда есть пакетные сценарии.

Как сказал Петр , если этот пример на самом деле , что вы пытаетесь достичь, вы можете выполнить то же самое гораздо более эффективно, действенно и безопасно на платформе с помощью следующего :

String[] filenames = new java.io.File("C:/").list();
2 голосов
/ 11 ноября 2010

Попробуйте ссылку

Вы не используете "cd", чтобы изменить каталог, из которого выполняются ваши команды. Вам нужен полный путь к исполняемому файлу, который вы хотите запустить.

Кроме того, перечислить содержимое каталога проще с классами File / Directory

1 голос
/ 11 ноября 2010

Каждый из ваших вызовов exec создает процесс.Второй и третий вызовы не выполняются в том же процессе оболочки, который вы создали в первом.Попробуйте поместить все команды в скрипт bat и запустить его за один вызов: rt.exec("cmd myfile.bat"); или аналогичный

0 голосов
/ 25 июня 2014

Поскольку я также столкнулся с той же проблемой и поскольку некоторые люди здесь отметили, что решение не работает для них, вот ссылка на пост, где было найдено рабочее решение.

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

Также см. «Обновление» в лучшем ответе по использованию терминала Cygwin

0 голосов
/ 11 ноября 2010

Запись в выходной поток из процесса является неправильным направлением. «Вне» в этом случае означает для вас процесс. Попробуйте получить / записать во входной поток для процесса и прочитать из выходного потока, чтобы увидеть результаты.

0 голосов
/ 11 ноября 2010

Это потому, что каждый runtime.exec(..) возвращает класс Process, который следует использовать после выполнения вместо вызова других команд классом Runtime

Если вы посмотрите на Process doc , вы увидите, что вы можете использовать

  • getInputStream()
  • getOutputStream()

, над которой вы должны работать, отправляя последовательные команды и извлекая выходные данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...