2013-01-20 3 views
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; 

я могу использовать блок исключения там также и выбросить исключение, но программа продолжает, как и раньше. Я использовал этот вызов в прошлом, но, похоже, он не выполняет никакой очистки и т. Д., Поэтому я делаю большую процедуру с закрытыми и бесплатными звонками ко всему, что я сделал, чтобы быть уверенным (и даже тогда я «Я не уверен ни в одном из за кулисами»).

Итак, как правильно обращаться с такими вещами?

Редактировать: Чтобы уточнить, я хочу узнать, как сделать программу, выполнить ее очистку, а затем ВЫЙТИ СЕЙЧАС и не делать никакого другого кода.

+0

Вы хотите чистый выход после некоторого условия? как насчет вызова Application.Terminate? – jachguate

+0

@jachguate Да, я хочу чистого выхода. Но этот вызов по-прежнему приводит к тому, что форма показана в тех случаях, когда отображение формы не будет логичным. – Glenn1234

+0

В каком из ваших вопросов вы заявляете, что не хотите, чтобы какая-либо форма отображалась? – jachguate

ответ

1

Вы можете указать глобальному объекту приложения завершить работу программы, вызвав Application.Terminate.

Завершение вызова для завершения программы. Вызовите Terminate, а не освободите объект приложения, , вы разрешите закрытию приложения упорядоченным образом.

Завершение вызова функции Windows 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 - гипотетический класс исключений, который вы можете объявить и никогда не обрабатывать в своих исключениях.

+0

Второй блок кода быстро разворачивает коробку, а затем завершается. У меня есть Delphi 3, здесь я тестирую его на данный момент (все это удобно для меня прямо сейчас), если это полезно знать. – Glenn1234

+0

Как насчет первого? – jachguate

+0

Показывает сообщение, затем мигает основная форма и завершается - в основном лучшее, что я могу сделать сейчас. – Glenn1234

2

IMHO единственный чистый способ будет проверять «Фатальные условия» перед запуском приложения.

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. 
+0

Ваш первый подход, который я пытался предложить, однако OP, похоже, беспокоится об изменении файлов * .dpr. – TLama

+0

@TLama вы удалили сообщение? Возможно, вы должны восстановить его, я бы удалил бы мою, если вы восстановите свою. На мой взгляд, если это возможно, чтобы избежать тяжелых прерываний, это должно быть сделано. – bummi

+0

Давайте будем держать это как есть. Ваш ответ обеспечивает более широкий охват, чем мой. – TLama

6

Чтобы выполнить ненормальное завершение вызова Halt(), передав код выхода.

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

В Windows это приводит к вызову TerminateProcess и остановит выполнение там и тогда.

Обратите внимание, что никакая очистка не выполняется, и обычно это то, что вы хотите. Поскольку вы выполняете эту проверку при запуске приложения, очистка не должна быть чистой.

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.