6

更新:D2007に固有のようです。D2010でも、以前のバージョンと同じように機能します。

次のように、EceptionHandlerブロックでキャッチされた例外のタイプに応じて終了コードを返したいと思います。

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.

残念ながら、D2007では、ExceptionブロックからHalt(n)を呼び出すと、Halt()に何を渡しても、常に終了コード1が返されます。

どうやら、例外ハンドラーを終了するとFinalizeが呼び出され、保留中の(中止されていない)例外がクリアされ、SysUtils.ExceptHandlerが呼び出されます。

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

そして、私が望んでいた終了コードに関係なく、私はそれを取得しHalt(1)ます!

したがって、問題は次のとおり
です。発生した例外に応じて、目的の終了コードを簡単に返すにはどうすればよいですか。

4

5 に答える 5

5

これは機能しますか?

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;

とにかく、これは D2010 で修正された D2007 のバグです。

于 2010-08-04T22:25:26.923 に答える
2

実際...意図したとおりに動作するようです....

私はあなたのコードを使用しました...

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.

Delphi 5 でコンパイルし、XP の DOS ボックスで実行しました...

C:\>test1
Enter error code:
111
EExternal: sdsdkfjh

C:\>echo %errorlevel%
111

C:\>

DOS エラー レベルは 0 ~ 65535 の範囲に制限されていることに注意してください。%errorlevel% をエコーするのが、エラー レベルを確認する最も簡単な方法です。

エラーレベルを読み取るとクリアされることを忘れないでください。

于 2010-08-04T20:13:18.800 に答える
2

クリーンアップせずにプログラムをすぐに中止し、終了コードを返したい場合は、ExitProcessを試してください。ただし、ExitProcess の使用に関するいくつかの注意事項については、記事を参照してください。

于 2010-08-04T20:16:55.810 に答える
0

Halt(I) を使用すると、メモリ リークが発生します (ReportMemoryLeaksOnShutdown:=true; で FastMM MemoryLeaks を有効にすると、メモリ リークが発生することがわかります)。

「クリーンな」Exit を使用し、終了する前に ExitCode を設定することをお勧めします。

たとえば、コンソール アプリのメイン セクションでは次のようになります。

ExitCode:=I;
exit;
于 2016-03-04T18:44:50.403 に答える
-1

組み込みの例外処理関数が気に入らない場合は、独自のものに置き換えます。

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 のままである場合、関数は 1 で終了するという Delphi の元の動作に戻りますが、終了コードがすでに別の値に設定されている場合は、代わりにその値で停止します。最初HaltにグローバルExitCode変数を設定するので、コードを変更する必要はありません (Exitcode変数には別の名前を付けますが)。を呼び出すとHalt、グローバルExitCode変数が設定され、プログラムのシャットダウンに進みます。例外ハンドラは がすでに設定されていることに気づき、1 ではなくその値でExitCode再呼び出しします。Halt

于 2010-08-04T20:41:59.627 に答える