写入标准输入并等待标准输出

发布于 2024-08-09 00:58:13 字数 4645 浏览 2 评论 0原文

我正在尝试创建一个线程,使 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...所以我想我不需要再刷新任何东西了,因为构造函数是:

new 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 set address "Local 区域连接 6" 静态 69.69.69.69

为什么第二个命令没有执行???

255.255.255.0

* 完成 *

更新 2:

一切似乎都工作得很好,直到老师在西班牙 Windows 环境中尝试我的应用程序....

我的代码如下所示:

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

我需要的是以某种方式将 netshWriter 编码设置为 Windows 默认值。

有人知道该由谁来做吗?

I'm trying to create a Thread that keeps netsh windows command-line tool open so I can execute netsh commands without open it every single time.

The thing is, once I've created the Thread, just the first command call works... the subsequent calls seems to have no effect.

Here is my code:

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

Thank you!!! =)

Update 1:

Ok... I'm now using a PrintWriter instead... so I think I don't need to flush anything anymore, since the constructor is:

new PrintWriter(netshOutStream, true); (just like Mr. Shiny told me)...

Suppose I decide to break the while loop when the first output line is available... I doesn't work either... the next command wont be executed.... My code now looks like:

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

and the output I get:

Executing: int ip set address "Local
Area Connection 6" static .69.69.69
255.255.255.0 netsh>.69.69.69 is not an acceptable value for addr.
Executing: int ip set address "Local
Area Connection 6" static 69.69.69.69

Why the second command is not executed???

255.255.255.0

* DONE *

Update 2:

Everything seemed to work just fine until a teacher tried my app in a spanish-windows enviroment....

my code looks like this:

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

and what i need is to somehow set the netshWriter encoding to the windows default.

Can anyone know who to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

白昼 2024-08-16 00:58:13

您正在关闭输出流。

You are closing the output stream.

情绪少女 2024-08-16 00:58:13

您需要将流处理移至单独的线程中。发生的情况是 inPipe.readLine() 正在阻塞等待 netsh 返回数据。 Apache 有一个处理进程处理的包。我会考虑使用它而不是自己滚动(http://commons.apache.org/exec/ )

You need to move the stream processing into separate threads. What's happening is that inPipe.readLine() is blocking waiting for netsh to return data. Apache has a package that deals with process handling. I'd look at using that instead of rolling your own (http://commons.apache.org/exec/)

枉心 2024-08-16 00:58:13

这在很多方面似乎都是错误的。

首先,为什么是 Runnable 对象?这永远不会传递到任何地方的线程。您创建的唯一线程不是 java 线程,而是由 exec() 创建的操作系统进程。

其次,您需要一种方法来知道 netsh 何时完成。读取 netsh 输出的循环将永远运行,因为当 netsh 关闭其标准输出时, readLine 只会返回 null (在您的情况下,永远不会)。您需要查找 netsh 在处理完您的请求后打印的一些标准内容。

正如其他人提到的,接近是不好的。使用冲洗。并希望 netsh 使用冲洗功能返回给您......

This seems wrong in many ways.

First, why a Runnable object? This isn't ever passed to a Thread anywhere. The only thread you're creating isn't a java thread, it is an OS process created by exec().

Second, you need a way to know when netsh is done. Your loop that reads the output of netsh will just run forever because readLine will only return null when netsh closes its standard out (which is never, in your case). You need to look for some standard thing that netsh prints when it is done processing your request.

And as others mentioned, close is bad. Use a flush. And hope netsh uses a flush back to you...

黒涩兲箜 2024-08-16 00:58:13

我会尝试:

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

netshWriter.println(command);

不 close() 流,自动刷新流,并使用编写器发送字符数据,而不是依赖平台“本机字符集”。

I'd try:

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

netshWriter.println(command);

No close()ing the stream, flush the stream automatically, and uses a writer to send character data rather than relying on the platforms "native character set".

念三年u 2024-08-16 00:58:13

您确实需要删除 close,否则您将永远无法执行另一个命令。当您说一旦 close() 调用被删除“它将不起作用”时,您的意思是没有命令被处理吗?

有可能,在发送命令的字节后,您需要发送某种确认键以便进程启动,好吧,处理它。如果您通常从键盘输入它,它可能就像回车一样简单,否则可能需要使用 Ctrl-D 或类似的键。

我会尝试替换 close() 行

netshOutStream.write('\n');

,看看是否有效。根据软件的不同,您可能需要更改发送的字符来表示命令结束,但这种通用方法应该可以帮助您完成。

编辑:

调用也是谨慎的

netshOutStream.flush();

在上述行之后 ;如果没有刷新,就不能保证您的数据将被写入,事实上,由于您使用的是 BufferedInputStream,我 99% 确信在刷新流之前不会写入任何内容。因此,为什么代码随后会阻塞,因为您正在等待响应,而进程还没有看到任何输入,并且正在等待您向其发送一些输入。

You do definitely need to remove the close, else you'll never be able to execute another command. When you say "it won't work" once the close() call removed, do you mean no commands are processed?

Chances are that after you send the bytes for the command, you need to send some kind of confirmation key for the process to start, well, processing it. If you'd normally enter this from the keyboard it might be as simple as a carriage return, otherwise it might need to be a Ctrl-D or similar.

I'd try replacing the close() line with

netshOutStream.write('\n');

and see if that works. Depending on the software you might need to change the character(s) you send to signify the end of the command, but this general approach should see you through.

EDIT:

It would also be prudent to call

netshOutStream.flush();

after the above lines; without the flush there's no guarantee that your data will be written and in fact, since you're using a BufferedInputStream I'm 99% sure that nothing will be written until the stream is flushed. Hence why the code afterwards blocks, as you're waiting for a response while the process has not seen any input yet either and is waiting for you to send it some.

执着的年纪 2024-08-16 00:58:13

我使用扫描仪而不是 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);
}

它执行这两个命令。

I've used scanner instead of BufferedReader, just because I like it. So this code works:

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

It executes both commands.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文