Java中执行的Windows进程无法终止

9

我正在使用Java在Windows上创建一个进程。我的问题是这个进程无法终止。下面是一个示例程序:

import java.io.IOException;

public class Test {

/**
 * @param args
 * @throws IOException
 * @throws InterruptedException
 */
public static void main(String[] args) throws IOException,
        InterruptedException {
    Process process = Runtime.getRuntime().exec("cmd /c dir");
    process.waitFor();
    }
}

由于我无法理解的原因,这个程序从未完成过。如果将“cmd /c dir”替换为ipconfig或其他某些内容,情况也是如此。
我可以使用ProcessExplorer看到java创建了cmd进程。这个示例显然是一个简化版;在我的原始程序中,我发现如果我在一段时间后调用process.destroy()并检查cmd进程的输出,命令会成功执行。
我已经尝试过各种版本的Java 1.5和1.6。我的操作系统是Windows XP Pro,SP 2。
3个回答

11

很可能您只需要读取进程的标准输出和错误输出,否则它可能会挂起,因为其输出缓冲区已满。如果将错误输出重定向到标准输出,这是最简单的方法,以确保安全性:

public static void main(String[] args) throws IOException,
                InterruptedException {
        String[] cmd = new String[] { "cmd.exe", "/C", "dir", "2>&1" };
        Process process = Runtime.getRuntime().exec(cmd);
        InputStream stdout = process.getInputStream();
        while( stdout.read() >= 0 ) { ; }
        process.waitFor();
    }
}

这个解决方案运行得非常好!但是2>&1的解释是什么? - frss-soft.com
1
@frss-soft.com - 这是将标准错误(2)重定向到标准输出(1)的语法。这样你只需要从标准输出读取,而不是同时读取标准输出和标准错误。在许多情况下,代码可以正常工作,但如果你运行的程序曾经向标准错误写入任何内容,如果没有这个语法,它可能会挂起。 - Eric Petroelje

9

请参考此链接了解详细解释。

您需要读取输入流。此外,Java进程不像DOS shell那样工作。您需要自己传递参数:

String[] cmd = new String[3];
cmd[0] = "cmd.exe" ;
cmd[1] = "/C" ;
cmd[2] = "dir";
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);

1
你并不完全正确。exec(String)的API文档说明参数是“系统命令”,而没有更详细的定义。“系统命令”很可能只是JVM将字符串传递给cmd.exe。 - JesperE
谢谢你的回答和链接!我应该有机会在周日检查一下有问题的机器。实际上,参数被正确传递了; 我可以在 Process Explorer 中看到它们。 - David Resnick

0
你应该尝试使用下面展示的ProcessBuilder。不确定有什么不同,但这解决了我们很多问题。
ProcessBuilder pb = new ProcessBuilder(CMD, ARG1, ARG2);  
Process p = pb.start();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接