代码之家  ›  专栏  ›  技术社区  ›  Francesca

如何从带有D2007的异常块返回带有Halt(n)的错误代码?

  •  6
  • Francesca  · 技术社区  · 15 年前

    :似乎是针对D2007的。它在D2010中工作,就像它在旧版本中工作一样。

    我想根据Eception处理程序块中捕获的异常类型返回退出代码,如下所示:

    program test;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils;
    
    var
      Exitcode: Integer;
    begin
      Writeln('Enter error code:');
      Readln(Exitcode);
      try
        raise EExternal.Create('sdsdkfjh');
      except
        on E:EExternal do
        begin
          Writeln(E.Classname, ': ', E.Message);
          Halt(Exitcode);
        end;
      end;
    end.
    

    从异常块调用Halt(n)总是返回退出代码1 ,无论您传递给Halt()的是什么。

    显然是因为从异常处理程序中退出会调用Finalize,Finalize会清除挂起的(非中止)异常,并调用SysUtils.ExceptHandler:

    procedure ExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer); far;
    begin
      ShowException(ExceptObject, ExceptAddr);
      Halt(1); // <= @#$##@#$!
    end;
    

    不管我想要什么退出密码我都能得到 Halt(1) !

    所以问题是:
    如何根据引发的异常返回所需的退出代码?

    5 回复  |  直到 15 年前
        1
  •  5
  •   Francesca    15 年前

    这样行吗?

    NeedHalt := False;
    try
      raise EExternal.Create('sdsdkfjh');
    except
      on E:EExternal do
      begin
        Writeln(E.Classname, ': ', E.Message);
        NeedHalt := True;
      end;
    end;
    if NeedHalt then
      Halt(Exitcode); 
    

    try
      raise EExternal.Create('sdsdkfjh');
    except
      on E:EExternal do
      begin
        Writeln(E.Classname, ': ', E.Message);
        AcquireExceptionObject;
        Halt(Exitcode); 
      end;
    end;
    

    无论如何: it's a bug in D2007, which was fixed in D2010

        2
  •  2
  •   Mike Warot    15 年前

    事实上。。。它似乎按预期工作。。。。

    program test1;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils;
    
    var
      Exitcode: Integer;
    begin
      Writeln('Enter error code:');
      Readln(Exitcode);
      try
        raise EExternal.Create('sdsdkfjh');
      except
        on E:EExternal do
        begin
          Writeln(E.Classname, ': ', E.Message);
          Halt(Exitcode);
        end;
      end;
    end.
    

    在Delphi5中编译,然后在XP下的DOS框中运行。。。

    C:\>test1
    Enter error code:
    111
    EExternal: sdsdkfjh
    
    C:\>echo %errorlevel%
    111
    
    C:\>
    

    请注意,DOS错误级别限制在0到65535之间。回显%errorlevel%是查看错误级别的最快方法。

    别忘了读取errorlevel会清除它。

        3
  •  2
  •   Mason Wheeler    15 年前

    ExitProcess . 不过,有关使用ExitProcess的一些注意事项,请参阅本文。

        4
  •  0
  •   MrTheV    10 年前

    使用halt(I)会产生内存泄漏(您可以看到,如果您使用ReportMemoryLeaksOnShutdown启用了FastMM MemoryLeaks:=true;)

    最好使用“干净”的出口,并在退出前设置ExitCode。

    例如,在控制台应用程序的主要部分:

    ExitCode:=I;
    exit;
    
        5
  •  -1
  •   Rob Kennedy    15 年前

    如果内置的异常处理函数不能满足您的需要,请用您自己的函数替换它:

    function ExitCodeExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer);
    begin
      ShowException(ExceptObject, ExceptAddr);
      if ExitCode = 0 then
        ExitCode := 1;
      Halt(ExitCode);
    end;
    

    将其分配给全局 System.ExceptProc

    ExceptProc := @ExitCodeExceptHandler;
    

    ExitCode 变量。如果它仍然是默认值0,那么函数将恢复到原来的Delphi行为,即使用1退出,但是如果退出代码已经设置为其他值,那么它将使用该值停止。第一件事 Halt 是否设置了全局 退出代码 变量,因此您的代码不需要进一步更改(尽管我会为 Exitcode 变量)。你的电话 停下 退出代码 退出代码 停下 使用该值而不是1。

    推荐文章