【问题标题】:Java runtime.exec does not execute correctlyJava runtime.exec 没有正确执行
【发布时间】:2014-02-20 09:21:25
【问题描述】:

我得到一个 exe 文件,我必须在 Windows Server 2008 R2 上使用 Java(版本 6)执行该文件。现在有一个我不太明白的问题。使用命令行执行文件时

"C:\test.exe param1 param2" 

它可以正常工作,但是当我使用

执行文件时
Process proc = Runtime.getRuntime().exec("C:\\test.exe param1 param2");
proc.waitFor();

我可以在 Windows 任务管理器中看到 test.exe 并且它开始运行(它会创建一个说明这一点的日志),但是它不再做任何事情。 test.exe 无休止地以 0% 运行,我必须手动终止该进程。这样做之后,java-program 会继续,并且

proc.exitValue()

是“1”,因此 java 识别出我已经终止了该进程。我也尝试在批处理文件中编写命令行并使用 .exec() 执行它,但它没有改变任何东西。

真正让我感到困惑的是,它可以通过 Windows 命令行完美运行,但不能通过 .exec() 运行。有谁知道什么可能导致这样的问题?还是更有可能是 test.exe 引起了问题?

致以最诚挚的问候

编辑:在 .exec 中写下错误的路径

【问题讨论】:

  • 也许stackoverflow.com/questions/8595748/java-runtime-exec 可以帮助你,似乎是一个类似的问题。
  • 当您在控制台中运行该程序时,它是否会在控制台中产生输出?还是从标准输入读取?
  • 在继续之前,请使用ProcessBuilder!
  • test.exe 是否输出大量文本?可能是它在尝试写入其输出时被阻止,而您似乎没有从中读取
  • 是的,它确实会在控制台和 log.txt 中产生大量输出。减少控制台中的输出可能会有所帮助(不过,我必须联系 test.exe-programm 的程序员才能这样做)?

标签: java windows-server-2008-r2 runtime.exec java-6


【解决方案1】:

由于您的程序产生大量输出,我的假设是它试图写入标准输出(在 Linux 下是管道,在 Windows 下不知道)。

试试这个:

final byte[] devnull = new byte[1024];

final ProcessBuilder builder = new ProcessBuilder("C:\\test.exe", "param1", "param2")
    .redirectErrorStream(true);
final Process p = builder.start();

final InputStream stdout = process.getInputStream();

// Purge stdout
while (stdout.read[devnull] != -1);

// Grab the process' exit code here

【讨论】:

    【解决方案2】:

    正如 fge 在 https://stackoverflow.com/a/21903969 中指出的那样,消耗进程产生的所有输出很重要——不仅在 Linux 上,而且在 Windows 上,不仅是标准输出,还有可能的错误。

    这种情况的一般模式可能如下所示:

    private static void runCommand(String command) throws IOException
    {
        Process process = Runtime.getRuntime().exec(command);
        String errorMessage = 
            new String(toByteArray(process.getErrorStream()));
        String outputMessage = 
            new String(toByteArray(process.getInputStream()));
        int exitValue = 0;
        try
        {
            exitValue = process.waitFor();
        }
        catch (InterruptedException e)
        {
            Thread.currentThread().interrupt();
        }
        System.out.println("Output message: "+outputMessage);
        System.out.println("Error message: "+errorMessage);
        System.out.println("Exit value: "+exitValue);
    }
    
    private static byte[] toByteArray(
        InputStream inputStream) throws IOException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte buffer[] = new byte[8192];
        while (true)
        {
            int read = inputStream.read(buffer);
            if (read == -1)
            {
                break;
            }
            baos.write(buffer, 0, read);
        }
        return baos.toByteArray();
    }
    

    【讨论】:

    • 即使我们不感兴趣,我们是否总是需要消耗输出?否则被调用的程序会冻结吗?
    • @JohnyTex 自从我使用它已经有一段时间了,但据我所知:是的,必须消耗输出,否则程序可能会出现“冻结”。
    【解决方案3】:
    "C:\test.exe param1 param2"
    

    你在那里有一个标签。试试这个:

    "C:\\test.exe param1 param2"
    

    如果进程在 stdout 或 stderr 上产生任何输出,则需要使用它。否则会阻塞。

    【讨论】:

    • 抱歉,我尝试将问题分解为最少的代码,并为问题复制了错误的 exec() 字符串。在 java-programm 中的路径就像你写的一样
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    相关资源
    最近更新 更多