Como en este hilo se daba información general, eso mismo hice yo.
Para el caso de jclDebug, ha de tenerse en cuenta 2 cosas:
- Hay que incluir en el primer formulario o Datamodule que crees el uses jclDebug, ya que realiza una inicialización en su unidad para empezar el "traceo" de excepciones.
- En la distribución de tu ejecutable, tienes que distribuir un archivo .map que se crea al compilar, (abrelo con el bloc de notas para saber de que hablo). En este caso se tiene que distribuir un par de megas más, pero perece la pena.
- Además de la información de jclDebug, se debe incluir las ventanas abiertas en tu aplicación (si son varias) para saber lo que hacia el usuario, (el objeto TScreen vale para eso).
-En cuanto al uso de compresores de ejecutables, acabo de probarlo, y efectivamente el compresor elimina la información de debug, por lo que interfiere con JCLDEBUG, como ya sabemos: no se puede tener todo
.
Para el primer punto, yo me he construido mi propia jclDebug, que unicamente cambia los procedimientos por funciones y devuelve el error en una variable. Os lo dejo aqui:
(El nombre de la unidad lleva el prefijo LP (Lepe) para que no interfiera con posibles modificaciones de la JCL)
Saludos
Código Delphi
[-]
unit lpJclDebug;
interface
function LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean):string;
procedure MyLogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean);
var Error:string; var UseMaxDeep:Boolean;
implementation
uses
JclDebug, JclHookExcept, TypInfo, Classes,sysutils;
function LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean):string;
var
TmpS: string;
ModInfo: TJclLocationInfo;
I: Integer;
ExceptionHandled: Boolean;
HandlerLocation: Pointer;
ExceptFrame: TJclExceptFrame;
MaxDeep, idx:Integer;
Log:TStringList;
begin
log:= TStringList.Create;
try
Log.Clear;
MaxDeep:=0;
TmpS := 'Exception ' + ExceptObj.ClassName;
if ExceptObj is Exception then
TmpS := TmpS + ': ' + Exception(ExceptObj).Message;
if IsOS then
TmpS := TmpS + ' (OS Exception)';
Log.Add(TmpS);
ModInfo := GetLocationInfo(ExceptAddr);
idx:= Log.Add(Format(
'Exception '+ #13#10+
' UnitName : %s' +#13#10+
' Procedure : %s' +#13#10+
' Line : %d'+
' OffsetLine : %d',
[ModInfo.UnitName,
ModInfo.ProcedureName,
ModInfo.LineNumber,
modinfo.offsetfromlinenumber]));
Inc(MaxDeep);
if stExceptFrame in JclStackTrackingOptions then
begin
I := 0;
ExceptionHandled := False;
while (UseMaxDeep or not ExceptionHandled) and
(I < JclLastExceptFrameList.Count) do
begin
ExceptFrame := JclLastExceptFrameList.Items[i];
ExceptionHandled := ExceptFrame.HandlerInfo(ExceptObj, HandlerLocation);
if (ExceptFrame.FrameKind = efkFinally) or
(ExceptFrame.FrameKind = efkUnknown) or
not ExceptionHandled then
HandlerLocation := ExceptFrame.CodeLocation;
ModInfo := GetLocationInfo(HandlerLocation);
TmpS := Format(
' EXCFRAME $%p (TIPO %s',
[ExceptFrame.ExcFrame,
GetEnumName(TypeInfo(TExceptFrameKind), Ord(ExceptFrame.FrameKind))]);
if ExceptionHandled then
TmpS := TmpS + ', handles exception)'
else
TmpS := TmpS + ')';
Inc(MaxDeep);
Log.Add(STRINGofchar(' ',MaxDeep*2)+Format(
' UnitName : %s' +
' Procedure : %s' +
' SourceName : %s' +
' Line : %d',
[ModInfo.UnitName,
ModInfo.ProcedureName,
ModInfo.SourceName,
ModInfo.LineNumber]));
Inc(I);
end;
end;
Log.Add('');
Log.Insert(idx+1,' Deep of Except frame-dump : '+IntToStr(MaxDeep));
finally
Result := Log.Text;
FreeAndNil(Log);
end;
end;
procedure MyLogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean);
begin
Error := LogException(ExceptObj, ExceptAddr, IsOS);
end;
initialization
UseMaxDeep:= False;
JclAddExceptNotifier(MyLogException);
JclStackTrackingOptions := JclStackTrackingOptions + [stExceptFrame];
JclStartExceptionTracking;
finalization
JclRemoveExceptNotifier(MyLogException);
end.
saludos