Как да изпълнявате cmd команди чрез Java

Опитвам се да изпълня аргументи от командния ред чрез 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.

(Преработих въпроса си, за да бъда по-конкретен. Следните отговори бяха полезни, но не отговарят на въпроса ми.)


person joe    schedule 11.11.2010    source източник
comment
Джо, ако все още смятате, че въпросът ви не е получил отговор, мисля, че трябва да предоставите повече информация. Моят отговор определено прави това, което искате да постигнете, а именно да изброявате файловете в C:\. Отговорите на Vincent и Carles ви показват как да изпълнявате множество команди на обвивката от едно извикване exec(). Не съм сигурен от какво не сте доволни на този етап.   -  person Andrzej Doyle    schedule 12.11.2010


Отговори (11)


Кодът, който публикувахте, стартира три различни процеса, всеки със своя собствена команда. За да отворите команден ред и след това да изпълните команда, опитайте следното (никога не съм го опитвал):

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) {
}
person Peter Knego    schedule 11.11.2010
comment
Благодаря. Това отваря командния ред, но не изпълнява командата cd или dir. - person joe; 11.11.2010
comment
Боже, обичам фрагменти от код с отказ от отговорност: Никога не съм го пробвал сам. ›_‹ - person b1nary.atr0phy; 28.08.2012
comment
Това отваря командния ред, но не изпълнява командата cd или dir, защо? - person Akhilesh Dhar Dubey; 21.04.2013
comment
защо е одобрен..невярно положителен! - person Sejwal; 14.08.2013
comment
Предполагам, че поне /n трябва да се промени на \n. Но като цяло изпълнената команда и методът за управление на черупка са доста съмнителни. - person eckes; 05.10.2014
comment
Отговорите по-долу съдържат действителния отговор. - person Mgamerz; 26.10.2014

Намерих това в 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_;
}
person Pepe    schedule 25.03.2011
comment
Страхотно, че връзката е невалидна, но кодовете, копирани тук, са достатъчни. - person mrmoment; 23.06.2014
comment
@tvanfosson Здравейте, имам едно съмнение! Работи за „cmd“, не мога да използвам това за „powershell“. Има ли някакво решение, което мога да следвам? - person GP cyborg; 27.10.2014

Ако искате да изпълните няколко команди в cmd обвивката, можете да създадете една команда по следния начин:

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

Тази страница обяснява повече.

person Vincent Ramdhanie    schedule 11.11.2010

Всяко изпълнение на exec ражда нов процес със собствена среда. Така че второто ви извикване не е свързано с първото по никакъв начин. Той просто ще промени собствената си работна директория и след това ще излезе (т.е. ефективно е без операция).

Ако искате да съставяте заявки, ще трябва да направите това в рамките на едно обаждане до exec. Bash позволява множество команди да бъдат посочени на един ред, ако са разделени с точка и запетая; Windows CMD може да позволи същото, а ако не, винаги има пакетни скриптове.

Както казва Пьотр, ако този пример е всъщност това, което се опитвате да постигнете, можете да извършите същото много по-ефективно, ефективно и безопасно за платформата със следното:

String[] filenames = new java.io.File("C:/").list();
person Andrzej Doyle    schedule 11.11.2010
comment
@Boris - проверете историята на въпросите, тя е редактирана през двата месеца, откакто публикувах този отговор. - person Andrzej Doyle; 18.01.2012

Опитайте това връзка

Не използвате "cd", за да промените директорията, от която да изпълнявате вашите команди. Имате нужда от пълния път на изпълнимия файл, който искате да изпълните.

Освен това изброяването на съдържанието на директория е по-лесно с класовете File/Directory

person Piotr    schedule 11.11.2010
comment
Отговорът не е свързан с въпроса - person Mert Serimer; 19.01.2016

Всяко от вашите извиквания на exec създава процес. Вашето второ и трето извикване не се изпълняват в същия процес на обвивка, който създавате в първия. Опитайте да поставите всички команди в bat скрипт и да го изпълните в едно извикване: rt.exec("cmd myfile.bat"); или подобен

person Carles Barrobés    schedule 11.11.2010
comment
Отговорът не е свързан с кода на въпроса - няма друго извикване на exec - person Boris Daich; 17.01.2012
comment
Имаше време, когато отговорих, но въпросът беше редактиран оттогава. Моля, вижте хронологията на редакциите на този въпрос, преди да гласувате против. - person Carles Barrobés; 18.01.2012

Това е така, защото всеки runtime.exec(..) връща Process клас, който трябва да се използва след изпълнението вместо извикването на други команди от Runtime класа

Ако погледнете Документ за процеса, ще видите които можете да използвате

  • getInputStream()
  • getOutputStream()

върху който трябва да работите, като изпращате последователните команди и извличате изхода..

person Jack    schedule 11.11.2010

Писането в изходящия поток от процеса е грешна посока. „вън“ в този случай означава от процеса за вас. Опитайте да получите/запишете във входния поток за процеса и да прочетете от изходния поток, за да видите резултатите.

person Kelly S. French    schedule 11.11.2010

Тъй като и аз се сблъсках със същия проблем и тъй като някои хора тук коментираха, че решението не работи за тях, ето връзката към публикацията, където е намерено работещо решение.

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

Вижте също „Актуализация“ в най-добрия отговор за използване на Cygwin терминал

person singe3    schedule 25.06.2014

Ето по-прост пример, който не изисква множество нишки:

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);
    }
}
person egerardus    schedule 22.10.2020

person    schedule
comment
Моля, добавете някакво обяснение към отговора си, така че другите да могат да се поучат от него - person Nico Haase; 22.10.2020