如何从Java启动过程中取消阻止?

时间:2009-04-16 10:38:16

标签: java process

当从cmd行执行一些命令(比如说'x')时,我收到以下消息: “....按任意键继续 。 。 。”。所以它等待用户输入解锁。

但是当我从java执行相同的命令('x')时:

Process p = Runtime.getRuntime().exec(cmd, null, cmdDir);
// here it blocks and cannot use outputstream to write somnething
p.getOutputStream().write(..);

代码块......

我试着在进程的输出流中写入一些东西,但是我怎么能这样做,代码永远不会到达那一行呢?

8 个答案:

答案 0 :(得分:2)

我认为(虽然不能肯定)你在谈论Windows而不是Unix?

如果是这样,命令行进程可能实际上没有等待stdin上的按键(或输入),而是等同于旧的DOS kbhit()函数。

AFAIK没有办法让这个功能相信键盘已被按下而没有按下键。

要测试此理论,请创建一个文本文件“input.txt”,其中包含一些空行,然后运行:

foo.exe < input.txt

这将显示您的程序是在等待stdin还是等待其他内容。

答案 1 :(得分:2)

您应该同时阅读子流程的输出和错误流。这些流的缓冲区大小是有限的。如果其中一个缓冲区已满,则子进程将阻塞。我认为这就是你的情况。

答案 2 :(得分:1)

我认为在Java中执行外部应用程序的推荐光线是使用ProcessBuilder。代码看起来像

//Launch the program
ArrayList<String> command = new ArrayList<String>();
command.add(_program);
command.add(param1);
...
command.add(param1);

ProcessBuilder builder = new ProcessBuilder(command);
//Redirect error stream to output stream
builder.redirectErrorStream(true);

Process process = null;
BufferedReader br = null;
try{
    process = builder.start();

    InputStream is = process.getInputStream();
    br = new BufferedReader( new InputStreamReader(is));
    String line;

    while ((line = br.readLine()) != null) {
         log.add(line);
    }
}catch (IOException e){
    e.printStackTrace();
}finally{
    try{
        br.close();
    }catch (IOException e){
        e.printStackTrace();
    }
}

流程对象有一个get [输入/输出/错误]流,可用于与程序交互。

答案 3 :(得分:0)

程序无法继续,因为它被阻止,期望用户输入。

一个选项是在单独的线程中启动外部进程,或者使用共享进程p的线程以便能够写入其流。

答案 4 :(得分:0)

我在this stackoverflow question写了一个命令行执行的答案。

你可能需要回复,因为你的回答会有点棘手。

在你的情况下,我可能需要给输入流gobbler类似回复频道:

 StreamGobbler outputGobbler = new StreamGobbler(
                                    proc.getInputStream(), "OUTPUT", 
                                    proc.getOutputStream());

并使其匹配模式并回复给定的输入流。

while ((line = br.readLine()) != null) {
    System.out.println(type + ">" + line);
    if (line.contains(PRESS_KEY_CONTINUE) {
        ostream.write("y".getBytes("US-ASCII")); 
        System.out.println("< y"); 
    }
}

希望这有帮助。

答案 5 :(得分:0)

所以这是我对这个问题的解决方法,灵感来自Alnitak的建议: 像这样运行命令:

Process p = Runtime.getRuntime().exec(cmd + " < c:\\someTextFile.txt", null, cmdDir);
...
int errCode = p.waitFor();
...

'someTextFile.txt'可以编程方式创建到临时目录中然后删除。

答案 6 :(得分:0)

使用PrintWriter模拟一些输入:

        Process p = Runtime.getRuntime().exec(cmd, null, cmdDir);
        //consume the proces's input stream
        ........
        // deblock
        OutputStream outputStream = p.getOutputStream();
        PrintWriter pw = new PrintWriter(outputStream);
        pw.write("ok");
        pw.flush();
        int errCode = p.waitFor();

答案 7 :(得分:0)

我有同样的问题,我找到了解决方案。它不是最优雅的,但它确实有效。

1 - 当您执行该过程时,您将从该过程获取inputStream 2 - 然后你创建一个循环接收提示中显示的消息(如果有的话) 3 - 当你看到你从“提示”得到“按一个键继续”,或者其他什么时,你就结束了过程

            // Creates the runtime and calls the command
        Process proc = Runtime.getRuntime().exec(Destino);

        // Get the proccess inputStream
        InputStream ips = proc.getInputStream();
        String output = "";

        int c = 0;

        // Read the output of the pro
        while ((c = ips.read()) != -1
                && !output.contains("Press any key to continue")) {
            output = output + (char)c;
        }

        // Destroy the proccess when you get the desired message
        proc.destroy();