4

Delphi プログラムで実際に解決できていない問題に遭遇し続けており、誰かがそれについて教えてくれるかどうか疑問に思っていました。トピックにあるように、壊滅的なエラーを適切に処理するにはどうすればよいでしょうか? 例えば:

// is file necessary for the program present?
if not FileExists(FilePath1) then
   begin
     raise Exception.Create(FilePath1 + ' does not exist and is required for this program to function.');
   // I obviously need to do something here to make the program QUIT and not have
   // any more code run.

     Application.Terminate;
     Abort;
   end;

そこで例外ユニットを使用して例外をスローすることもできますが、プログラムは以前と同じように続行されます。過去に停止呼び出しを使用したことがありますが、クリーンアップなどを行わないように見えるため、念のために行ったすべてのことに対してクローズ呼び出しとフリー呼び出しを行う大きな手順を作成することになります (それでも私は舞台裏のことはわかりません)。

では、そのようなものを処理する正しい方法は何ですか?

編集:明確にするために、プログラムに必要なクリーンアップを実行させてから、今すぐ終了し、他のコードを実行しないようにする方法について知りたいです。

4

4 に答える 4

6

異常終了を実行するには、終了コードを渡して Halt() を呼び出します。

if CatastropicErrorDetected then
begin
  ... show error message
  Halt(1);
end;

Windows では、これによりTerminateProcessが呼び出され、そこで実行が停止します。

クリーンアップが実行されないことに注意してください。通常はそれが必要です。アプリケーションの起動時にこのチェックを実行しているため、クリーンアップするものは何もないはずです。

于 2013-01-20T08:37:59.497 に答える
2

私見の唯一のクリーンな方法は、アプリケーションが実行される前に「致命的な状態」をチェックすることです。

program Project2;

uses
  Forms,Dialogs,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  ReportMemoryLeaksOnShutDown := true;
  Application.Initialize;
  if True then // your condition here
    begin
      MessageDLG('Fatal Error',mtError,[mbok],0);
    end
  else
    begin
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end;
end.

他のアプローチには副作用があります

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
    FSL:TStringList;
  public
   Destructor Destroy;override;
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

destructor TForm1.Destroy;
begin
  FreeAndNil(FSL);
  Showmessage('Will never be seen with Application.Terminate + HALT');
  inherited;
end;

procedure TForm1.FormCreate(Sender: TObject);
const
  Testing=0; // try 1 and 2 too
begin

   FSL:=TStringList.Create;
   Try
      raise Exception.Create('Terminating now');
   except
     case Testing of
         0: begin
             // exception object will not be freed other code will be prevented, Form won't be shown
             Application.Terminate;
             HALT;
            end;
         1: begin
             // exception object will not be freed Form won't be shown
             HALT;
            end;
         2: begin
             // clean but Form will be shown
             Application.Terminate;
            end;

     end;
   end;

end;

end.
于 2013-01-20T08:19:21.350 に答える
1

を呼び出して、アプリケーション グローバル オブジェクトにプログラムを終了するように指示できますApplication.Terminate

プログラムでアプリケーションを終了するには、Terminate を呼び出します。アプリケーション オブジェクトを解放するのではなく、Terminate を呼び出すことで、アプリケーションを正常な方法でシャットダウンできます

Terminate は、Windows API の PostQuitMessage 関数を呼び出して、アプリケーションの正常なシャットダウンを実行します。終了は即時ではありません。

呼び出しはスタックの奥深くで発生する可能性があるため、 Exception を発生させることもできます。実行がメイン アプリケーション ループに到達し、デフォルトの例外ハンドラーがそれをキャッチできるようにするために、それを処理しないようにプログラムをコーディングします。

そうすれば、アプリケーションで実行されるコードが増えるのを効果的に防ぐことができます。

コードでは、次のようになります。

if not FileExists(FilePath1) then
  begin
    MessageDlg(FilePath1 + ' does not exist and is required for this program to function.',
               mtWarning, [mbOK], 0);

    Application.Terminate;
    Abort;  //raising a EAbort just as an example
  end;

このコードが呼び出される場所によっては、メッセージを直接表示するのではなく、メッセージで例外を発生させ、アプリケーション オブジェクトのデフォルトの HandleException メソッドにメッセージを表示させることをお勧めします。

if not FileExists(FilePath1) then
  begin
    Application.Terminate;
    raise EMyFatalException.Create(FilePath1 
      + ' does not exist and is required for this program to function.');
  end;

私にはどちらがより自然に見えますか。EMyFatalException は、except 句で宣言でき、決して処理できない架空の例外クラスです。

于 2013-01-20T06:22:31.387 に答える
1

Application.OnException独自のハンドラーを作成できます。例:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure HandleException(Sender: TObject; E: Exception);
  end;

var
  Form1: TForm1;

type
  EMyFatalError = class(Exception);

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Application.OnException:= HandleException;
  raise EMyFatalError.Create('OOPS!');
end;

procedure TForm1.HandleException(Sender: TObject; E: Exception);
begin
  Application.ShowException(E);
  if E is EMyFatalError then
    Application.Terminate;
end;

end.
于 2013-01-20T09:25:30.677 に答える