Manejador de excepciones avanzadas con Delphi

Para mi ejemplo haré reposting, y utilizaré el ejemplo que escribió Sergey Shirokov y Alex P en Advanced Exception Handler. En su artículo comentan concretamente lo que yo quiero obtener de la pila. Para la obtención de los datos avanzados, necesitaré el siguiente componente: ExWatcher de la mano de Tomek Guz (Solo la versión para Delphi 5). Además utilizaremos el proyecto demo, llamado ExWatcherDemo.
- Instalando el componente ExWatcher


- Ejecutando la demo



- map2dbg

Una vez descargada la aplicación, la copiamos dentro de nuestra aplicación demo, y ejecutamos lo siguiente desde el intérprete de comandos:
map2dbg.exe exwatcherdemo.exe
y nos aparecerá el siguiente resultado:
converted 4150 symbols
Ahora, si ejecutamos el ejemplo y lanzamos alguna excepción obtendremos todas las llamadas de la Call Stack en nuestro TMemo:

Aquí os dejo con el proyecto de prueba que he utilizado: ExWatcherDemo Project.rar. Y el código fuente de la unidad principal para que veáis lo fácil que es utilizar el componente:
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, clExWatcher, ShowExcept;
type
TMainForm = class(TForm)
btnDelphiException: TButton;
btnDelphiSafeCallException: TButton;
btnSystemException: TButton;
clExceptWatcher: TclExceptWatcher;
btnSystemSafeCallException: TButton;
btnTryExcept: TButton;
memStackLog: TMemo;
procedure clExceptWatcherDelphiException(Sender: TObject; E: Exception;
EI: TclExceptionInformation; StackTracer: TclStackTracer);
procedure clExceptWatcherDelphiSafeCallException(Sender,
Target: TObject; E: Exception; EI: TclExceptionInformation;
StackTracer: TclStackTracer);
procedure clExceptWatcherSystemException(Sender: TObject;
EI: TclExceptionInformation; StackTracer: TclStackTracer);
procedure clExceptWatcherSystemSafeCallException(Sender,
Target: TObject; EI: TclExceptionInformation;
var NotifyTarget: Boolean; StackTracer: TclStackTracer);
procedure btnDelphiExceptionClick(Sender: TObject);
procedure btnDelphiSafeCallExceptionClick(Sender: TObject);
procedure btnSystemExceptionClick(Sender: TObject);
procedure btnSystemSafeCallExceptionClick(Sender: TObject);
procedure btnTryExceptClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
procedure SimulateDelphiException();
procedure SimulateSystemException();
procedure SimulateDelphiSafeCallException(); safecall;
procedure SimulateSystemSafeCallException(); safecall;
procedure ShowStack(Frames: TclStackFrames);
procedure ExceptionHandler(Sender: TObject; E: Exception);
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
procedure TMainForm.clExceptWatcherDelphiException(Sender: TObject;
E: Exception; EI: TclExceptionInformation; StackTracer: TclStackTracer);
begin
memStackLog.Clear();
memStackLog.Lines.Add('Delphi Exception:');
ShowStack(StackTracer.GetCallStack(EI));
end;
procedure TMainForm.clExceptWatcherSystemException(Sender: TObject;
EI: TclExceptionInformation; StackTracer: TclStackTracer);
begin
memStackLog.Clear();
memStackLog.Lines.Add('System Exception:');
ShowStack(StackTracer.GetCallStack(EI));
end;
procedure TMainForm.clExceptWatcherDelphiSafeCallException(Sender,
Target: TObject; E: Exception; EI: TclExceptionInformation;
StackTracer: TclStackTracer);
begin
memStackLog.Clear();
memStackLog.Lines.Add('Delphi SafeCall Exception:');
ShowStack(StackTracer.GetCallStack(EI));
end;
procedure TMainForm.clExceptWatcherSystemSafeCallException(Sender,
Target: TObject; EI: TclExceptionInformation; var NotifyTarget: Boolean;
StackTracer: TclStackTracer);
begin
memStackLog.Clear();
memStackLog.Lines.Add('System SafeCall Exception:');
ShowStack(StackTracer.GetCallStack(EI));
end;
procedure TMainForm.btnDelphiExceptionClick(Sender: TObject);
begin
SimulateDelphiException();
end;
procedure TMainForm.btnSystemExceptionClick(Sender: TObject);
begin
SimulateSystemException();
end;
procedure TMainForm.btnDelphiSafeCallExceptionClick(Sender: TObject);
begin
SimulateDelphiSafeCallException();
end;
procedure TMainForm.btnSystemSafeCallExceptionClick(Sender: TObject);
begin
SimulateSystemSafeCallException();
end;
procedure TMainForm.btnTryExceptClick(Sender: TObject);
begin
try
try
SimulateSystemException();
except
raise;
end;
except
end;
end;
procedure TMainForm.SimulateDelphiException;
begin
raise Exception.Create('Test Delphi exception');
end;
procedure TMainForm.SimulateSystemException;
var
p: PChar;
begin
p := PChar(5);
p^ := #9; //Access Violation here
end;
procedure TMainForm.SimulateDelphiSafeCallException;
begin
raise Exception.Create('Test Delphi SafeCall exception');
end;
procedure TMainForm.SimulateSystemSafeCallException;
var
p: PChar;
begin
p := PChar(5);
p^ := #9; //Access Violation here
end;
procedure TMainForm.ShowStack(Frames: TclStackFrames);
var
i: Integer;
begin
memStackLog.Lines.BeginUpdate();
for i := 0 to Frames.Count - 1 do
begin
memStackLog.Lines.Add(Format('%x: %s - %s', [Integer(Frames[i].CallAddress),
ExtractFileName(Frames[i].ModuleName), Frames[i].FunctionName]));
end;
memStackLog.Lines.EndUpdate();
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
Application.OnException := ExceptionHandler;
end;
procedure TMainForm.ExceptionHandler(Sender: TObject; E: Exception);
begin
ShowExceptionForm(E.Message);
end;
end.
- Enlaces de interés:
Madshi.net.
EurekaLog.
This comment has been removed by the author.
ReplyDeleteHi there Jordi! It seems to be an absolutely great component. But, woah! @#$**)!, it doesn't work for me on Vista x64! It just appears the last line, none of the call stack. At first I thought it was my fault by installation problems. Then, I had a try putting the same .exe on a winXP x32 machine, and it perfectly worked! Vista seems to be having fun with us... Can anyone have a try on Vista x32?
ReplyDeleteBTW, thank you for the post Jordi!
Hi!, that's the problem with de .dbg information, it only works with 32 bits. Don't worry about that, I'll take a look. Thank you for your comment!
ReplyDeleteYou can find more information from here:
ReplyDeletewww.madshi.net/enumStuff.zip