有一些我一直在努力的东西,我真的没有用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;
我也可以在那里使用异常单元并抛出异常,但程序会像以前一样继续。我过去曾经使用过停止呼叫,但它似乎没有进行任何清理等等,所以我最终制定了一个大程序,通过近距离和免费调用我所做的一切就是为了确保(即使那时我我不确定任何幕后的东西。
那么处理这类事情的正确方法是什么?
编辑:为了澄清,我想知道如何让程序执行它需要做的清理,然后立即退出而不执行任何其他代码。
答案 0 :(得分:6)
要执行异常终止,请调用Halt()传递退出代码。
if CatastropicErrorDetected then
begin
... show error message
Halt(1);
end;
在Windows上,这会导致调用TerminateProcess并在那时停止执行。
您注意到没有执行清理,通常这就是您想要的。由于您在应用程序启动时执行此检查,因此无需清理任何内容。
答案 1 :(得分: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.
答案 2 :(得分:1)
您可以通过调用Application.Terminate
来指示应用程序全局对象终止程序。
调用Terminate以编程方式结束应用程序。通过调用Terminate而不是释放应用程序对象,允许应用程序以有序的方式关闭。
终止调用Windows API PostQuitMessage函数以执行应用程序的有序关闭。终止不是立竿见影的。
由于调用可以在堆栈中更深入地发生,因此您也可以raise an 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子句中处理。
答案 3 :(得分: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.