Как выполнять команды 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.
(Я изменил свой вопрос, чтобы быть более конкретным. Следующие ответы были полезны, но не отвечаем на мой вопрос.)
9 ответов
Код, который вы разместили, запускает три разных процесса, каждый со своей командой. Чтобы открыть командную строку и затем запустить команду, попробуйте следующее (сам никогда не пробовал):
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) {
}
Я нашел это на 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_;
}
Если вы хотите запустить несколько команд в оболочке cmd, вы можете создать одну команду, например:
rt.exec("cmd /c start cmd.exe /K \"cd c:/ && dir\"");
Эта страница объясняет больше.
Каждое исполнение exec
порождает новый процесс со своей собственной средой. Таким образом, ваш второй вызов никак не связан с первым. Он просто изменит свой рабочий каталог и затем выйдет (т. Е. Фактически он не работает).
Если вы хотите составить запрос, вам нужно сделать это в течение одного вызова exec
, Bash позволяет указывать несколько команд в одной строке, если они разделены точкой с запятой; Windows CMD может разрешать то же самое, и если нет, то всегда есть пакетные сценарии.
Как говорит Петр, если этот пример действительно является тем, чего вы пытаетесь достичь, вы можете выполнить то же самое гораздо более эффективно, действенно и безопасно на платформе с помощью следующего:
String[] filenames = new java.io.File("C:/").list();
Попробуйте эту ссылку
Вы не используете "cd", чтобы изменить каталог, из которого выполняются ваши команды. Вам нужен полный путь к исполняемому файлу, который вы хотите запустить.
Кроме того, составление списка содержимого каталога проще с классами File/Directory.
Каждый из ваших вызовов exec создает процесс. Второй и третий вызовы не выполняются в том же процессе оболочки, который вы создали в первом. Попробуйте поместить все команды в скрипт bat и запустить его за один вызов:rt.exec("cmd myfile.bat");
или похожие
Это потому что каждый runtime.exec(..)
возвращает Process
класс, который должен использоваться после выполнения вместо того, чтобы вызывать другие команды Runtime
учебный класс
Если вы посмотрите на Process Doc, вы увидите, что вы можете использовать
getInputStream()
getOutputStream()
на котором вы должны работать, отправляя последовательные команды и получая выходные данные..
Запись в исходящий поток из процесса - неправильное направление. "Вне" в этом случае означает для вас процесс. Попробуйте получить / записать во входной поток для процесса и прочитать из выходного потока, чтобы увидеть результаты.
Поскольку я также столкнулся с той же проблемой и поскольку некоторые люди здесь отметили, что решение не работает для них, вот ссылка на пост, где было найдено рабочее решение.
/questions/9951792/s-java-zapustite-neskolko-komand-v-odnom-okne-cmdexe/9951801#9951801
Также см. "Обновление" в лучшем ответе по использованию терминала Cygwin.
Вот более простой пример, не требующий нескольких потоков:
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);
}
}
try {
String command = "Command here";
Runtime.getRuntime().exec("cmd /c start cmd.exe /K " + command);
} catch (IOException e) {
e.printStackTrace();
}