Написание стандартного ввода и ожидание стандартного вывода - PullRequest
1 голос
/ 28 октября 2009

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

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

Вот мой код:

public class NetshThread implements Runnable{
 private static Process netshProcess = null;
 private static BufferedInputStream netshInStream = null;
 private static BufferedOutputStream netshOutStream = null;
 public BufferedReader inPipe = null;

 public void run(){
  startNetsh();
 }

 public void startNetsh(){
  try {
   netshProcess = Runtime.getRuntime().exec("netsh");
   netshInStream = new BufferedInputStream(netshProcess.getInputStream());
   netshOutStream =  new BufferedOutputStream(netshProcess.getOutputStream());
   inPipe = new BufferedReader(new InputStreamReader(netshInStream));
  } catch (IOException e) {
   e.printStackTrace();
  }
 } 

 public void executeCommand(String command){
  System.out.println("Executing: " + command);
  try {
   String str = "";
   netshOutStream.write(command.getBytes());
   netshOutStream.close();
   while ((str = inPipe.readLine()) != null) {
                System.out.println(str);
            }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 public void closeNetsh(){
  executeCommand("exit");
 }

 public static void main(String[] args){
  NetshThread nthread = new NetshThread();
  nthread.run();
  String command = "int ip set address " +
    "\"Local Area Connection 6\" static .69.69.69 255.255.255.0";
  nthread.executeCommand(command);
  command = "int ip set address " +
    "\"Local Area Connection 6\" static 69.69.69.69 255.255.255.0";
  nthread.executeCommand(command);
  System.out.println("*** DONE ***");
 }
}

Спасибо !!! =)

Обновление 1:

Хорошо ... Теперь я использую PrintWriter ... так что я думаю, что мне больше не нужно ничего сбрасывать, поскольку конструктор:

новый PrintWriter (netshOutStream, true); (как сказал мне мистер Шини) ...

Предположим, я решил разорвать цикл while, когда первая строка вывода доступна ... Я тоже не работаю ... Следующая команда не будет выполнена .... Мой код теперь выглядит так:

import java.io.*;

public class NetshThread implements Runnable{
    private static Process netshProcess = null;
    private static BufferedInputStream netshInStream = null;
    private static BufferedOutputStream netshOutStream = null;
    public BufferedReader inPipe = null;
    private PrintWriter netshWriter = null;

    public void run(){
        startNetsh();       
    }

    public void startNetsh(){
        try {
            netshProcess = Runtime.getRuntime().exec("netsh");
            netshInStream = new BufferedInputStream(netshProcess.getInputStream());
            netshOutStream =  new BufferedOutputStream(netshProcess.getOutputStream());
            netshWriter = new PrintWriter(netshOutStream, true);
            inPipe = new BufferedReader(new InputStreamReader(netshInStream));
        } catch (IOException e) {
            e.printStackTrace();
        }
    } 

    public void executeCommand(String command){
        System.out.println("Executing: " + command);
        try {
            String str = "";
            netshWriter.println(command);
            while ((str = inPipe.readLine()) != null) {
                System.out.println(str);
                break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void closeNetsh(){
        executeCommand("exit");
    }

    public static void main(String[] args){     
        NetshThread nthread = new NetshThread();
        Thread xs = new Thread(nthread);
        xs.run();
        String command = "int ip set address " +
                "\"Local Area Connection 6\" static .69.69.69 255.255.255.0";
        nthread.executeCommand(command);
        command = "int ip set address " +
                "\"Local Area Connection 6\" static 69.69.69.69 255.255.255.0";
        nthread.executeCommand(command);
        System.out.println("*** DONE ***");
    }
}

и вывод, который я получаю:

Выполнение: int ip set address "Local Площадь подключения 6 "статическая .69.69.69 255.255.255.0 netsh> .69.69.69 не является допустимым значением для addr. Выполнение: int ip установить адрес "Local Площадь подключения 6 "статический 69.69.69.69

Почему вторая команда не выполняется ???

255.255.255.0

* СОВЕРШЕНО *

Обновление 2:

Казалось, все работало очень хорошо, пока учитель не попробовал мое приложение в среде испанских окон ....

мой код выглядит так:

Scanner fi = новый сканер (netshProcess.getInputStream ());

public void executeCommand(String command) {
        System.out.println("Executing: " + command);
        String str = "";
        netshWriter.println(command);
        fi.skip("\\s*");
        str = fi.nextLine();
        System.out.println(str);
}

и мне нужно как-то установить для кодировки netshWriter значение по умолчанию для окон.

Кто-нибудь может знать, кому это делать?

Ответы [ 6 ]

3 голосов
/ 28 октября 2009

Вы закрываете выходной поток.

2 голосов
/ 28 октября 2009

Вам необходимо переместить поток обработки в отдельные потоки. Происходит следующее: inPipe.readLine () блокирует ожидание, когда netsh вернет данные Apache имеет пакет, который занимается обработкой процессов. Я бы посоветовал использовать это вместо того, чтобы кататься самостоятельно (http://commons.apache.org/exec/)

1 голос
/ 28 октября 2009

Это кажется неправильным во многих отношениях.

Во-первых, почему объект Runnable? Это никогда не передается в поток нигде. Единственный поток, который вы создаете, это не поток Java, это процесс ОС, созданный exec ().

Во-вторых, вам нужен способ узнать, когда закончится netsh. Ваш цикл, который читает выходные данные netsh, просто будет работать вечно, потому что readLine вернет ноль только тогда, когда netsh закроет свой стандарт (что никогда не происходит в вашем случае). Вам нужно искать какую-то стандартную вещь, которую netsh печатает, когда завершает обработку вашего запроса.

И, как уже упоминалось, близко - это плохо. Используйте флеш. И надеюсь, что netsh использует флеш обратно к вам ...

0 голосов
/ 28 октября 2009

Я использовал сканер вместо BufferedReader, просто потому, что мне это нравится. Итак, этот код работает:

Scanner fi = new Scanner(netshProcess.getInputStream());


public void executeCommand(String command) {
    System.out.println("Executing: " + command);
    String str = "";
    netshWriter.println(command);
    fi.skip("\\s*");
    str = fi.nextLine();
    System.out.println(str);
}

Выполняет обе команды.

0 голосов
/ 28 октября 2009

Я бы попробовал:

PrintWriter netshWriter = new PrintWriter(netshOutputStream, true); // auto-flush writer

netshWriter.println(command);

Не закрывать () поток, автоматически очищать поток и использовать средство записи для отправки символьных данных, а не полагаться на "собственный набор символов" платформ.

0 голосов
/ 28 октября 2009

Вам определенно необходимо удалить close, иначе вы никогда не сможете выполнить другую команду. Когда вы говорите «это не сработает» после удаления вызова close (), вы имеете в виду нет команд, обработанных?

Скорее всего, после того, как вы отправите байты для команды, вам нужно отправить какой-то ключ подтверждения для запуска процесса, ну, ну, конечно, его обработки. Если вы обычно вводите это с клавиатуры, это может быть так же просто, как возврат каретки, в противном случае это может быть Ctrl-D или аналогичный.

Я бы попробовал заменить строку close () на

netshOutStream.write('\n');

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

EDIT:

Было бы также разумно позвонить

netshOutStream.flush();

после вышеуказанных строк; без сброса нет никакой гарантии, что ваши данные будут записаны, и фактически, поскольку вы используете BufferedInputStream, я на 99% уверен, что ничего не будет записано до тех пор, пока поток не будет сброшен. Следовательно, почему код впоследствии блокируется, так как вы ожидаете ответа, в то время как процесс еще не видел никаких входных данных и ждет, пока you его отправит.

...