问题
I am trying to create a log system on my program that will log debugging messages on text files, and I want to save the exact place in the code where the log message called, but I don't want to use Assert function because it creates exceptions and this system is not for logging exceptions only, also I have to write some debugging info.
example usning assert:
procedure AnyProcedure();
begin
try
Assert(1=0);
except
on E: Exception do
Log.AddLine('Log occurred is '+E.Message+' : Start');//Log occurred is "c:\progr~..jkdj.pas" at line [29]
end;
//....some code
try
Assert(1=0);
except
on E: Exception do
Log.AddLine('Log occurred is '+E.Message+' : Step1 done');//Log occurred is "c:\progr~..jkdj.pas" at line [37]
end;
//....some code
try
Assert(1=0);
except
on E: Exception do
Log.AddLine('Log occurred is '+E.Message+' : Step2 done');//Log occurred is "c:\progr~..jkdj.pas" at line [45]
end;
//....some code
try
Assert(1=0);
except
on E: Exception do
Log.AddLine('Log occurred is '+E.Message+' : Step3 done');//Log occurred is "c:\progr~..jkdj.pas" at line [53]
end;
//....some code
try
Assert(1=0);
except
on E: Exception do
Log.AddLine('Log '+E.Message+' : End');//Log occurred is "c:\progr~..jkdj.pas" at line [61]
end;
end;
this works fine the only thing that it raises an exception and the code become too big, so I can't use a function -see next example function LogMessage- and call it in another place because the line will be the same always also the file name will be where the LogMessage function implemented:
not working example:
procedure LogMessage(AMessage: String);
var AFile, ALine: String;
begin
try
Assert(1=0); //line 29
except
on E: Exception do
begin
AFile:= Copy(E.Message, Pos(' (', E.Message)+2, Pos(', line ', E.Message)-Pos(' (', E.Message)-2);
ALine:= Copy(E.Message, Pos(', line ', E.Message)+7, Pos(')', E.Message)-Pos(', line ', E.Message)-7);
ShowMessage('Log occurred in file "'+AFile+'" at line ['+ALine+'] : '+AMessage);
end;
end;
end;
procedure AnyProcedure();
begin
LogMessage('Start'); //Log occurred in file "c:\progr~....jkashdj.pas" at line [29]
//....
LogMessage('step1'); //Log occurred in file "c:\progr~....jkashdj.pas" at line [29]
//....
LogMessage('step2'); //Log occurred in file "c:\progr~....jkashdj.pas" at line [29]
//....
LogMessage('step3'); //Log occurred in file "c:\progr~....jkashdj.pas" at line [29]
//....
LogMessage('end');
end
please help, and thanks in advance.
回答1:
You can bind your own TAssertErrorProc procedure to the AssertErrorProc variable. You might write something like this:
procedure OnAssert(const Message, Filename: string; LineNumber: Integer;
ErrorAddr: Pointer);
begin
ShowMessage(Format('Assert in file "%s" at line %d.', [Filename, LineNumber]));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
AssertErrorProc := OnAssert;
end;
回答2:
The easiest way to map from the instruction pointer to unit name and line number is to use one of the various debugging libraries: madExcept, EurekaLog, JclDebug etc.
These tools all rely on the detailed map file that is produced by the linker. Although these libraries are best known for producing bug reports from unexpected exceptions, they have all the functionality that you need.
来源:https://stackoverflow.com/questions/16459608/delphi-how-to-get-current-code-line-current-unit-current-function-without-u