【问题标题】:Java ProcessBuilder process waiting for inputJava ProcessBuilder 进程等待输入
【发布时间】:2014-09-16 21:05:32
【问题描述】:

当通过 ProcessBuilder(特别是“GetMac /s”)运行命令行命令时,如果它抛出错误或正常返回,我可以读取错误或它返回的 MAC 地址,但如果它提示用户输入(某些 pc在网络上使用 getmac 时需要密码)进程将挂起等待密码。

这是从命令行运行时该命令的作用:

这是我用于该过程的代码:

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 地址时自动获取它们,这样用户就不必手动输入它。所以如果你知道更好的方法来获取远程电脑的 MAC,请告诉我,我会用它来代替。

我意识到 java 可能不是最好的语言,但它是我目前唯一知道的语言,这只是我在工作中休息的一个有趣的小项目。

**编辑:如果它需要密码,我只想忽略那台电脑并终止进程并继续下一台电脑

【问题讨论】:

    标签: java windows process


    【解决方案1】:

    你需要处理所有与Process相关的Stream,包括InputStream、ErrorStream和OutputStream。您在命令行上看到的文本将通过 InputStream,然后您需要通过 OutputStream 传递请求的信息。

    您需要在各自的线程中读取 InputStream 和 ErrorStream。如果它们传递文本,我经常将它们包装在 Scanner 对象中,并且我经常将 OutputStream 包装在 BufferedOutputStream 和 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:我的尝试被复制你的代码并保留你的builder.inheritIO(); 行搞砸了。如果您将其保留在那里,则流捕获将不起作用。摆脱它,吞噬你的信息流。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-19
    • 1970-01-01
    • 1970-01-01
    • 2015-09-19
    • 2013-08-09
    • 1970-01-01
    • 2013-05-25
    相关资源
    最近更新 更多