使用 ProcessBuilder/Runtime.exec() 启动的外部进程在 XP 上失败,但在 Win 7 上工作

发布于 2025-01-03 22:19:18 字数 1498 浏览 2 评论 0 原文

我正在开发一个Java程序,它必须获取机器序列号、CPU序列号等。在Windows上,WMI接口是查询此类信息的最佳方法,使用命令行查询的标准方法是

wmic bios get serialnumber

生成输出:

SerialNumber
WWV46RT609A3467173E

将其翻译成 Java,我使用了 Runtime.exec() 和 ProcessBuilder,如下所示: (注释的 Process p 是我之前所做的)。这里,组件和项目对应于上面命令行中的“BIOS”和“序列号”。

    String ret = "";
    ProcessBuilder pb = new ProcessBuilder("wmic", component, "get", item);
    pb.redirectErrorStream(true);
    // Process p = Runtime.getRuntime().exec(
    // "wmic " + component + " get " + item);
    Process p = pb.start();
    InputStreamReader isr = new InputStreamReader(p.getInputStream());
    BufferedReader input = new BufferedReader(isr);
    String str;
    while ((str = input.readLine()) != null) {
        if (str.equalsIgnoreCase(item) || StringUtils.isBlank(str)) {
            continue;
        }
        ret = str.trim();
    }
    input.close(); 
    isr.close();
    System.out.println(ret); 

此代码片段在 Windows 7 上完美运行,但在 Windows XP 上挂起。从命令行使用 wmic 适用于两种操作系统。 我在此处读到,处理 stdout 和 stderr 时存在问题被调用的进程,因此redirectErrorStream() 调用。

为什么在 Windows 7 上可以完美运行,但在 XP 上却失败?除了生成一个单独的线程(又名 'StreamGobbler'? (链接的示例非常古老,早于 ProcessBuilder 类及其redirectErrorStream() 调用。

I am working on a Java program that has to fetch the machine serial number, CPU serial number etc. On Windows, the WMI interface is the best way to query for such information, and the standard way to query using the commandline is

wmic bios get serialnumber

which produces output:

SerialNumber
WWV46RT609A3467173E

Translating this into Java, I have used both Runtime.exec() and a ProcessBuilder like so:
(The commented Process p is what I did previously). Here, component and item correspond to 'bios' and 'serialnumber' in the commandline above.

    String ret = "";
    ProcessBuilder pb = new ProcessBuilder("wmic", component, "get", item);
    pb.redirectErrorStream(true);
    // Process p = Runtime.getRuntime().exec(
    // "wmic " + component + " get " + item);
    Process p = pb.start();
    InputStreamReader isr = new InputStreamReader(p.getInputStream());
    BufferedReader input = new BufferedReader(isr);
    String str;
    while ((str = input.readLine()) != null) {
        if (str.equalsIgnoreCase(item) || StringUtils.isBlank(str)) {
            continue;
        }
        ret = str.trim();
    }
    input.close(); 
    isr.close();
    System.out.println(ret); 

This snippet works perfectly on Windows 7, but hangs on Windows XP. Using wmic from the commandline works on both OSes.
I read here that there's a problem with handling both stdout and stderr of the called process, hence the redirectErrorStream() call.

Why does it work flawlessly on Windows 7 but fail on XP? Is there a way other than spawning a separate thread, aka 'StreamGobbler'? (The linked example is quite ancient, and predates the ProcessBuilder class, with its redirectErrorStream() call.

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

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

发布评论

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

评论(2

清君侧 2025-01-10 22:19:18

我希望您现在已经解决了这个问题。如果没有,这就是您需要做的。首先,我也遇到了同样的问题,并发现这是 bufferedReader 问题。它陷入了死锁情况,导致 windows xp 挂起。解决方案是通过在命令中附加“

 String[] command = {"CMD", "/C", "WMIC COMPUTERSYSTEM GET USERNAME <NUL "} and executing this command. 

I hope that you have by now got a resolution to this issue. If not, this is what you need to do. First, I also encountered with the same issues and came to discover that it is bufferedReader issue. It is gets into a deadlock situation that resulting into windows xp hanging. The solution is to simulate the end of line (eof) to the bufferedreader by appending "<NUL" the the command.

 String[] command = {"CMD", "/C", "WMIC COMPUTERSYSTEM GET USERNAME <NUL "} and executing this command. 
无声无音无过去 2025-01-10 22:19:18

您必须使用线程来捕获输出(标准和错误)。

您还可以查看这个 Apache 库

You have to use threads to capture ouputs (standard & error).

You can also take a look at this Apache library.

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