简体   繁体   English

如何解除对Java启动进程的阻止?

[英]How can I unblock from a Java started process?

When executing some command(let's say 'x') from cmd line, I get the following message: "....Press any key to continue . . .". 当从cmd行执行某些命令(比如说“ x”)时,我收到以下消息:“ ....按任意键继续...。”。 So it waits for user input to unblock. 因此,它等待用户输入解除阻止。

But when I execute the same command ('x') from java: 但是当我从Java执行相同的命令('x')时:

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

the code blocks... 代码块...

I tried to write something into the process's output stream, but how can i do that sice the code never reaches that line ? 我试图在进程的输出流中写入一些内容,但是我该如何做,以确保代码从未到达该行?

I think (although can't be certain) that you're talking about Windows rather than Unix? 我认为(虽然不能确定)您是在谈论Windows而不是Unix?

If so, it's possible that the command line process isn't actually waiting for a key press (or input) on stdin but instead doing the equivalent of the old DOS kbhit() function. 如果是这样,则命令行进程实际上可能不是在等待stdin上的按键(或输入),而是等效于旧的DOS kbhit()函数。

AFAIK there's no way to make that function believe that the keyboard has been pressed without actually pressing a key. AFAIK无法使该功能相信没有实际按下键就已经按下了键盘。

To test this theory, create a text file "input.txt" with some blank lines in it, and run: 要测试该理论,请创建一个文本文件“ input.txt”,其中包含一些空行,然后运行:

foo.exe < input.txt

That will show whether your program is waiting on stdin or on something else. 这将显示您的程序正在等待stdin还是其他等待。

You should read the ouput and error streams of your subprocess simultaneously. 您应该同时读取子流程的输出和错误流。 The buffer size of these streams is limited. 这些流的缓冲区大小是有限的。 If one of the buffers gets full the subprocess will block. 如果其中一个缓冲区已满,则子进程将阻塞。 I think that is what happens in your case. 我认为您的情况就是如此。

I think the recommended ray of executing external applications in Java is using a ProcessBuilder. 我认为在Java中执行外部应用程序的推荐方法是使用ProcessBuilder。 The code looks like 代码看起来像

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

The process object has a get[Input/Output/Error]Stream that could be used to interact with the program. 流程对象具有可用于与程序进行交互的get [Input / Output / Error] Stream。

I had the same problem and I found a solution. 我遇到了同样的问题,并且找到了解决方案。 It ins´t the most elegant, but it works. 它不是最优雅的,但是可以工作。

1 - when you execute the process, you get the inputStream from the process 2 - Then you make a loop receiving the message shown in the prompt, if there was one 3 - When you see that you got from "prompt" the "press a key to continue", or whatever, you end the proccess 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();

The program doesn't continue because it is blocked expecting input from the user. 该程序无法继续,因为它已被阻止,期望用户输入。

An option is to launch the outer process in a separate thread, or use threads sharing the Process p in order to be able to write to its stream. 一种选择是在单独的线程中启动外部进程,或使用共享进程p的线程以便能够写入其流。

I wrote an answer to command line execution at this stackoverflow question . 我在这个stackoverflow问题上写了命令行执行的答案。

Yours is a bit more tricky since you probably need to reply. 您的问题比较棘手,因为您可能需要回复。

In your case it might me necessary to give the input stream gobbler something like a reply channel: 在您的情况下,我可能需要给输入流放牧者一些类似回复频道的内容:

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

and make it match a pattern and reply on the given input stream. 使其与模式匹配并在给定的输入流上回复。

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

Hope this helps. 希望这可以帮助。

So this is my workaround to this problem, inspired from Alnitak's suggestion: Run the command like this: 因此,这是我从Alnitak的建议得到启发后解决此问题的方法:运行以下命令:

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

the 'someTextFile.txt' can be programatically created into the temporary dir then deleted. 可以通过编程方式将“ someTextFile.txt”创建到临时目录中,然后将其删除。

Use a PrintWriter to simulate some input: 使用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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何为以Java启动的nogui进程创建控制台窗口? - How can i create a Console Window for a nogui process started in java? 如何在 shell 脚本中杀死刚启动的 Java 进程? - How can I kill a just started Java process in shell script? 如何在 Java 中检查进程是否已启动 - How to I check whether a process is started or not in Java 如何验证我的MAVEN_OPTS环境变量是否正在传递给正在启动的java进程? - How can I verify that my MAVEN_OPTS environment variable is being passed to the java process being started? 如何从首选项页面获取路径并在按钮启动的过程中使用它? - How can I fetch a path from a preference page and use it in a process started by a button? 如何杀死从我的Java应用程序启动的cmd进程? - How to kill a cmd process which was started from my java application? 如何以编程方式在启动它的同一脚本中终止正在运行的进程? - How can I programmatically terminate a running process in the same script that started it? 如果从Java启动,子进程将忽略SIGQUIT - Child process ignores SIGQUIT if started from Java 从线程开始杀死Java进程 - Killing a Java Process started from a thread Hadoop Process从Java代码开始 - Hadoop Process started from Java Code
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM