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 回答