9

当我从命令行运行 ant 时,如果失败,我会得到一个非零退出状态($? 在 UNIX 上,%ERRORLEVEL% 在 Windows 上)。但是我们有一个运行 ant 的 Java 程序(通过 ProcessBuilder),当 ant 失败时,在 Windows 上我们无法获得退出状态。

我刚刚用这个简单的 ant 测试文件验证了这一点:

<project name="x" default="a">
  <target name="a">
    <fail/>
  </target>
</project>

在 UNIX 上,运行 ant 会打印一条失败消息,并回显 $? 之后打印 1。在 Windows 上,运行 ant 或 ant.bat 打印失败消息,然后回显 %ERRORLEVEL% 打印 1。

现在,使用下面的测试程序: 在 UNIX 上,java Run ant 打印一条失败消息,并回显 $? 之后打印 1. 在 Windows 上, java Run ant 找不到要运行的名为 ant 的程序,但 java Run ant.bat 打印失败消息,但回显 %ERRORLEVEL% 之后打印0。是什么赋予了?

我们依赖于能够在运行 ant 后检查退出状态。反正我们是。为什么我们不能以编程方式依赖它?

测试程序:

import java.io.*;

public class Run {
  public static void main(String[] args) throws IOException, InterruptedException {
    ProcessBuilder pb = new ProcessBuilder(args);
    Process p = pb.start();
    ProcThread stdout = new ProcThread(p.getInputStream(), System.out);
    ProcThread stderr = new ProcThread(p.getErrorStream(), System.err);
    stdout.start();
    stderr.start();
    int errorLevel = p.waitFor();
    stdout.join();
    stderr.join();
    IOException outE = stdout.getException();
    if (outE != null)
      throw(outE);
    IOException errE = stdout.getException();
    if (errE != null)
      throw(errE);
    System.exit(errorLevel);
  }

  static class ProcThread extends Thread {
    BufferedReader input;
    PrintStream out;
    IOException ex;

    ProcThread(InputStream is, PrintStream out) {
      input = new BufferedReader(new InputStreamReader(is));
      this.out = out;
    }

    @Override
    public void run() {
      String line;
      try {
        while ((line = input.readLine()) != null)
          out.println(line);
      } catch (IOException e) {
        setException(e);
      }
    }

    private void setException(IOException e) {
      this.ex = e;
    }

    public IOException getException() {
      return ex;
    }
  }
}
4

8 回答 8

7

我通过创建一个批处理文件解决了这个问题比上面的要好一点,但仍然很神秘):

文件内容myant.bat

@echo off
rem RunAnt simply calls ant -- correctly returns errorlevel for callers
call ant.bat %*

至关重要的是,在call.

于 2010-10-21T11:51:45.857 回答
2

另一个问题 - 如果您在 BAT 文件中调用 ANT 并且您有兴趣保存错误级别值,则必须将调用排除在 if/else 块之外。

例如,这不起作用(......在一些例程中间):

if "%DUMP_ARGS%"=="no" (
   call ant %ANT_TARGETS%
   set ANT_RETURN=%errorlevel%
)

您必须按如下方式中断呼叫(...放置在该例程之外):

:call_ant
call ant %ANT_TARGETS%
set ANT_RETURN=%errorlevel%
goto :eof

(......在一些例行公事的中间)

if "%DUMP_ARGS%"=="no" (
    call :call_ant
)
于 2012-01-09T16:43:49.233 回答
2

我通过创建两个额外的批处理文件解决了这个问题(不是很好,但它有效):

文件内容myant.bat

call ant2.bat %*

文件内容ant2.bat

call ant.bat %*
if errorlevel 1 (goto ERROR_EXIT)
exit /B 0
:ERROR_EXIT
exit /B 1

现在我可以从 java 调用myant.batProcess我得到正确的退出值。

抱歉,我不能说为什么会这样。这只是多次尝试的结果。

于 2009-09-22T03:53:14.540 回答
2

一个快速补丁是在 ANT.BAT 文件的末尾添加以下内容:

exit /b %ANT_ERROR%

这个问题很久以前就存在了,最近修复了。请参阅错误 41039

它应该在 ANT 版本 1.8.2 或更高版本中准备就绪。

于 2010-12-16T10:32:26.090 回答
1

你需要通过它的 .bat 文件运行 Ant 吗?它只是一个 java 程序,您可以通过直接实例化和执行 Ant 运行时在 VM 内部执行。看看ant.bat里面,看看它的Main类是什么,直接执行。

于 2009-09-21T21:30:46.377 回答
0

我用谷歌搜索了这个线程,发现 tangens 的答案几乎解决了我的问题:退出编码在 Windows 上始终为 0 from ant.bat,即使我故意使 ant 构建失败;我需要从 TFS 构建脚本中获取退出代码,它表明即使%ERRORLEVEL%在 TFS 构建中也找不到退出代码。

但是,我必须删除/Bfromexit行,否则,它仍然总是显示退出代码 0。

于 2010-05-10T21:15:24.330 回答
0

对于 Windows 上的旧版本 Ant,这是一个长期存在的问题。我相信它已在 1.7.0 版中修复。

有关详细信息,请参阅此错误,有关解决此问题的方法,请参阅此讨论

于 2009-09-21T21:39:34.250 回答
0

我解决了替换IF ERRORLEVEL 1IF %ERRORLEVEL% NEQ 0

call ant

IF %ERRORLEVEL% NEQ 0 GOTO :build_error
于 2016-01-26T09:46:11.623 回答