Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

windows - Java ProcessBuilder process waiting for input

When running a command line command via ProcessBuilder (specifically "GetMac /s") if it throws an error or returns normally and I can read the error or the MAC address that it returns but if it prompts the user input (some pc's on the network require a password when using getmac) the process will just hang waiting for the password.

Here is what the command does when run from command line: enter image description here

Here is the code I'm using for the process:

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();
        }
    }
}

The reason I need the mac is for making a wake on lan program and want to automatically get any new pc's mac addresses when they're detected so the user doesn't have to enter it manually. so if you know a better way of getting the MAC of a remote pc by all means let me know and I'll use that instead.

I realize java probably isn't the best language to be using for this but it's the only one I know at the moment and this is just fun little project for my downtime at work.

**Edit: if it requries a password I just want to ignore that PC and kill the process and move on to the next PC

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You need to handle all the Streams associated with the Process, including the InputStream, ErrorStream and OutputStream. The text you see on the command line will be coming through the InputStream, and you'll then want to pass information requested through the OutputStream.

You'll want to read the InputStream and the ErrorStream both in their own Threads. I often wrap them in a Scanner object if they're passing text, and I often wrap the OutputStream in a BufferedOutputStream, and that in a PrintStream object.


e.g.,

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);
      }      
   }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...