2013-11-22 20 views
5

Delphi에서 전역 예외 처리기를 설정했습니다. 일부 심각한 예외에서는 오류 메시지가 표시됩니다 (Halt()가 뒤에 있음). 오류 메시지가 표시되는 동안 Delphi는 더 많은 오류를 발생시키는 타이머 이벤트를 처리하는 메시지 대기열을 처리합니다.Delphis에서 타이머 이벤트를 무시하는 방법 MessageDlg

내가 원하는 것은 타이머 이벤트를 처리하지 않는 오류 대화 상자를 표시하는 것입니다. Delphi에서 어떻게 가능합니까?

편집 : 나는 Dialogs.MessageDlg (...)를 사용하여 메시지를 표시합니다. 이 같은

+0

내가 메시지 만이 그 오류 대화로 해결하는 것이 통과 것이다 있도록 "최종 오류 메시지가 표시됩니다"와 앱의 OnMsg 요격 일부 글로벌 플래그를 가지고해야한다고 생각, 다른 메시지를 걸러 낼 수 있습니다 http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Forms_TApplication_OnMessage.html –

+2

'TTimer' (s)를 사용하면 모든' 대화 상자를 표시하기 전에'Application '에 대한 TTimer를 호출하십시오. 그냥 생각. – kobik

+0

@kobik 그렇다면 전역 예외 처리기는 모든 TTimer를 인식해야합니다. 나는 다른 솔루션을 선호합니다. –

답변

4

당신은 대기 필터링 할 수 있습니다 메시지.

procedure TMainForm.ApplicationMessage(var Msg: TMsg; var Handled: Boolean); 
begin 
    if ShowingFatalErrorDialog then 
    if Msg.Message = WM_TIMER then 
     Handled := True; 
end; 

직접 Application.OnMessage 해당 이벤트 핸들러를 할당하거나 TApplicationEvents 개체를 사용 하나.

분명히 ShowingFatalErrorDialog에 대한 구현을 제공해야하지만, 그렇게하는 것이 분명한 이유입니다.

+0

대화 상자에서 메시지를 필터링하려고합니다. 그러나 TApplicationEvents를 사용하면 글로벌 바 (vars)에 의존하지 않고도 이러한 방식으로 작동합니다. 감사. –

+0

블랙리스트 방식은 여기서 막 다른 골목이라고 생각합니다. 하나 대신 화이트리스트 정책을 구현해야합니다 –

+0

@ Arioch'The 당신은 내가 생각하는 질문에 그 의견을 게시하기위한 것입니다. –

2

시도 뭔가 : TApplication.OnMessage와 같은 WM_TIMER 같은

... 
    private 
    FAboutToTerminate: Boolean; 
    end; 

... 

type 
    ESevereError = class(Exception); 

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    Tag := Tag + 1; 
    if Tag > 2 then 
    raise ESevereError.Create('Error'); 
end; 

procedure TForm1.ApplicationEvents1Exception(Sender: TObject; 
    E: Exception); 
begin 
    if (E is ESevereError) and (not FAboutToTerminate) then 
    begin 
    FAboutToTerminate := True; 
    Application.ShowException(E); 
    Application.Terminate; 
    end; 
end; 
+0

고마워, 나는 나의 마지막 구현에서 모든 예외를 삼키기 위해 당신의 아이디어를 사용했다. 하지만 내 주요 초점은 첫 번째 줄에 치명적인 타이머 이벤트를 생성하지 않는 것이 었습니다. –

+1

코드의 FreeAndNil (E) 부분이 잘못되었다고 생각합니다. 설명서에 따르면, 나는 예외를 해제하지 않아야한다고 생각합니다. 이것은 나를 위해 [액세스 위반] (http://stackoverflow.com/q/22630972/2523663)로 이어집니다. [이 설명] (http://stackoverflow.com/a/22668566/2523663)을보십시오. –

+0

고마워요! 어쩌면'ApplicationEvents.CancelDispatch'가 AV를 막는 데 도움이 될 수도 있지만 예외를 파기하는 것은 확실합니다. – NGLN

1

참고 용으로 다음 두 코드를 혼합하여 사용합니다. TFatalErrorAppEvents와

procedure SaveShowErrorMessage(...) 
begin 
    with TFatalErrorAppEvents.Create(nil) do //avoid timer and further exceptions 
    try 
     Dialogs.MessageDlg(...); 
    finally 
     Free; 
    end; 
end; 

는 다음과 같이

type 
    TFatalErrorAppEvents = class(TApplicationEvents) 
    protected 
     procedure KillTimerMessages(var Msg: tagMSG; var Handled: Boolean); 
     procedure IgnoreAllExceptions(Sender: TObject; E: Exception); 
    public 
     constructor Create(AOwner: TComponent); override; 
    end; 


constructor TFatalErrorAppEvents.Create(AOwner: TComponent); 
begin 
    inherited; 
    OnMessage := KillTimerMessages; 
    OnException := IgnoreAllExceptions; 
end; 

procedure TFatalErrorAppEvents.IgnoreAllExceptions(Sender: TObject; E: Exception); 
begin 
    //in case of an Exception do nothing here to ignore the exception 
end; 

procedure TFatalErrorAppEvents.KillTimerMessages(var Msg: tagMSG; var Handled: Boolean); 
begin 
    if (Msg.message = WM_TIMER) then 
     Handled := True; 
end;