Java ProcessBuilder进程等待输入

3
当通过ProcessBuilder运行命令行命令(特别是"GetMac / s")时,如果它抛出错误或正常返回并且我可以读取其返回的错误或MAC地址,但如果它提示用户输入(某些计算机在使用getmac时需要密码),则该进程将挂起等待密码。
以下是从命令行运行该命令的操作: enter image description here 以下是我用于该进程的代码:
package testing;
import java.io.IOException;

class test1 {
    public static void main(String[] args){
        String hostName = "testpc";
        ProcessBuilder builder = new ProcessBuilder("getmac", "/s", hostName, "/nh");
        builder.inheritIO();
        try {
            Process proc = builder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

我需要Mac电脑来制作远程唤醒程序,希望能自动获取任何新PC的MAC地址,以便用户无需手动输入。如果您知道更好的方法来获取远程PC的MAC地址,请告诉我,我会使用该方法。
我知道Java可能不是用于此的最佳语言,但它是我目前唯一掌握的语言,而且这只是我工作闲暇时间里的一个有趣小项目。
**编辑:如果需要密码,我只想忽略该PC并终止进程,转而继续下一个PC。
1个回答

5
你需要处理与进程相关联的所有流,包括InputStream、ErrorStream和OutputStream。你在命令行上看到的文本将通过InputStream传输,然后你会想要通过OutputStream传递请求的信息。
你需要分别在自己的线程中读取InputStream和ErrorStream。如果它们正在传递文本,我经常使用Scanner对象封装它们,而且我经常使用BufferedOutputStream封装OutputStream,再将其封装在PrintStream对象中。
例如:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Scanner;

class Test1 {
   private static PrintStream out;

   public static void main(String[] args) {
      String hostName = "testpc";
      String[] commands = {"getmac", "/s", hostName,
            "/nh"};
      ProcessBuilder builder = new ProcessBuilder(commands);

      // builder.inheritIO(); // I avoid this. It was messing me up.

      try {
         Process proc = builder.start();
         InputStream errStream = proc.getErrorStream();
         InputStream inStream = proc.getInputStream();
         OutputStream outStream = proc.getOutputStream();

         new Thread(new StreamGobbler("in", out, inStream)).start();
         new Thread(new StreamGobbler("err", out, errStream)).start();

         out = new PrintStream(new BufferedOutputStream(outStream));
         int errorCode = proc.waitFor();
         System.out.println("error code: " + errorCode);
      } catch (IOException e) {
         e.printStackTrace();
      } catch (InterruptedException e) {
         e.printStackTrace();
      } finally {
         if (out != null) {
            out.close();
         }
      }
   }
}

class StreamGobbler implements Runnable {
   private PrintStream out;
   private Scanner inScanner;
   private String name;

   public StreamGobbler(String name, PrintStream out, InputStream inStream) {
      this.name = name;
      this.out = out;
      inScanner = new Scanner(new BufferedInputStream(inStream));
   }

   @Override
   public void run() {
      while (inScanner.hasNextLine()) {
         String line = inScanner.nextLine();

         // do something with the line!
         // check if requesting password

         System.out.printf("%s: %s%n", name, line);
      }      
   }
}

如果我这样做,仍然会得到相同的结果。就像实际的密码提示没有通过InputStream发送一样。如果可以在不需要密码的情况下获取MAC地址(它不会提示任何内容),它将在控制台上打印MAC地址。但是,如果确实需要密码,我无从知晓,因为它不会打印出来(如果需要密码,我只想忽略那个特定的电脑并终止该进程)。 - Orion
@Orion:我尝试复制你的代码并保留了builder.inheritIO();这一行,但结果变得混乱了。如果你保留它,流捕获就无法正常工作。把它去掉,然后吞下你的流。 - Hovercraft Full Of Eels

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接