【问题标题】:Using Process Runtime Exec To Run A Batch File With "Start"使用 Process Runtime Exec 通过“开始”运行批处理文件
【发布时间】:2011-11-03 09:56:34
【问题描述】:

我想通过 Java 的 Runtime::exec 方法运行一个 Windows 批处理文件。在我的批处理文件中,我执行另一个批处理文件来运行 Java 程序。第一个批处理文件使用“start”来执行第二个批处理文件。

我希望我的主线程,即调用 Runtime::exec 的主线程,只等到第一个批处理文件完成,而不关心第二个批处理文件。我在 2 个单独的线程中使用 Process::getInputStream() 和 Process::getErrorStream() 中的所有内容。我的主线程(执行 Runtime::exec 的线程)一直等到 2 个流消费线程完成,然后再继续。

但是,我发现我的主线程总是阻塞,直到第二个批处理文件完成,因为即使在第一个批处理文件完成执行之后,我的流消费线程继续读取。如何让他们忽略第二个批处理文件的输出和错误流?

这是我在主线程中执行第一个批处理文件的方式:

Runtime runtime = Runtime.getRuntime();
String[] cmd = new String[]{"cmd.exe", "/C", "batch1.bat"};
Process proc = runtime.exec(cmd);
StreamLogger errorLogger = new StreamLogger(proc.getErrorStream()); // consume
StreamLogger outputLogger = new StreamLogger(proc.getInputStream()); // consume
errorLogger.start(); // start reading the error stream in another thread
outputLogger.start(); // start reading the output stream in another thread
returnCode = proc.waitFor();
log.debug("Obtained return code");
errorLogger.join();
outputLogger.join();
log.debug("Finished reading from streams");

batch1.bat 看起来像这样:

start "" batch2.bat
exit

在batch2.bat中,我运行了一个java程序(我试过用java.exe或javaw.exe运行它)

javaw.exe -cp . MyProgram 1>outlog 2>errlog

总之,当我运行我的主线程时,我可以在 batch1.bat 完成后获得返回码(即 waitFor() 解除阻塞),但主线程阻塞直到 batch2.bat 和 javaw.exe 终止,因为“errorLogger.join()”和“outputLogger.join()”。我对读取 batch2.bat 的输出不感兴趣; batch1.bat 完成后如何让我的主线程返回?

【问题讨论】:

    标签: java process exec runtime.exec


    【解决方案1】:

    当您使用waitFor 方法时,如果batch2.batbatch1.bat 运行在同一进程上,这肯定会发生。

    在我的脑海中,我想说你有几个选择(如果你真的想等待第一个批处理文件完成执行):

    1. 使用能够为 batch2.bat 调用独立进程的脚本。
    2. outputlogger 发送一个标记,告诉您的父进程batch1.bat 已完成执行并且不要使用waitFor。这将帮助您继续执行代码逻辑。

    【讨论】:

    • 感谢您的回答,实际上,我的代码在batch1.bat完成后并没有在waitFor方法处阻塞,而是在“errorLogger.join()”和“outputLogger.join()”处阻塞,直到batch2.bat 完成。
    • 在您的 batch1.bat 中尝试start cmd /c batch2.bat。此外,在您最近的运行中(当您的代码在 errorLogger.join() 处阻塞时),日志中是否有这一行 "Obtained return code"
    • 谢谢,我试过start cmd /c batch2.bat,但得到了相同的结果;我的日志在 batch1 完成后显示"Obtained return code",我的代码仍然阻塞在 errorLogger.join() 直到 batch2 终止。
    • 嗯,我看到它发生的方式是,在batch2.bat 完成之前,您的流不会返回EOF。因此,join() 方法会保留您的主线程,直到 errorloggeroutputlogger 线程完成执行。这只是意味着流正在从一个进程batch1.bat 收集数据,该进程在batch2.bat 完成之前不会结束。因此,您必须弄清楚如何从脚本中调用新进程,或者根本不使用join()
    • 谢谢,也许我毕竟不会使用 join()
    【解决方案2】:

    您是否尝试过通过 start /b batch2.bat 调用您的第二批?

    【讨论】:

    • 不,我会尝试一下并在此处发布结果
    猜你喜欢
    • 2019-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多