![]() |
aktuelle Quellcodezeile im Programm ermitteln
Ich bin gerade dabei meine Logfileroutine aufzupeppen. Ich habe mal in einem Logfile von einem anderen Programm folgendes gesehen und finde es extrem cool:
Code:
Sprich da wird die aktuelle Codezeilennummer wie in diesem Fall Zeile "309" mit in das Programm einkompiliert. Kann man sowas in Delphi auch machen?
[2014-07-30 23:06:18.875] Programm Error - F:\relbranch-2_0\Adapter.cpp:309 - running failed with exception: System exception
Mir geht es nur darum, dass ich im Logfile und im Ouputdebugstring punktuell die Quellzeile automatisch ermitteln kann, und nicht jedesmal mühsam den Funktionsnamen als Marker reinschreiben muß. Lg, jus |
AW: aktuelle Quellcodezeile im Programm ermitteln
Schau Dir mal Assertions an.
|
AW: aktuelle Quellcodezeile im Programm ermitteln
Zitat:
So wie ich es verstanden habe, kommt bei Assert immer eine Messagebox. Damit ich die Ausgabe in einer Logdatei verwenden kann, habe ich folgende Quick&Dirty Lösung zum Umleiten der Meldung verwendet, für den Fall, dass jemand so eine Lösung benötigt:
Delphi-Quellcode:
Ich habe den obigen von "
procedure AssertErrorHandler(const Message, Filename: string; LineNumber: Integer; ErrorAddr: Pointer);
implementation procedure DoMessage(Message, Filename: String; LineNumber: Integer; ErrorAddr: Pointer); var S: String; begin S := Format('%s (%s, line %d, address $%x)', [Message, Filename, LineNumber, Pred(Integer(ErrorAddr))]); WriteToLogFile(s);// <----- ist nur exemplarisch gemeint ;-) //OutputDebugString(PChar(S)); end; procedure AssertErrorHandler(const Message, Filename: string; LineNumber: Integer; ErrorAddr: Pointer); { No local variables. Not compiler generated temporary variables. } { Using the call stack here will cause Access Violation errors. } begin DoMessage(Message, Filename, LineNumber, ErrorAddr); // raise EMyAssert.Create('Boom!'); end; procedure TForm1.FormCreate(Sender: TObject); begin System.AssertErrorProc := @AssertErrorHandler; end; ![]() Lg, jus |
AW: aktuelle Quellcodezeile im Programm ermitteln
Uns zumindest würde die reine Zeilennummer nicht besonders helfen, wenn es um Fehler geht. Daher speichern wir dabei normalerweise den kompletten Stacktrace bei einem Fehler.
|
AW: aktuelle Quellcodezeile im Programm ermitteln
Zitat:
Die JCL (JEDI Component Library) kann das zum Beispiel. Ein neues leeres VCL Projekt erstellen, einen TButton drauf, deppelklicken und folgenden Quelltext darauf legen:
Delphi-Quellcode:
Es kommt dann z.B. folgendes im Logfile an:
...
procedure TForm1.Button1Click(Sender: TObject); begin StrToInt('Zwei'); end; ...
Code:
Wir loggen noch viel viel mehr Informationen zu jedem Fehler.
Exception class: EConvertError
Exception message: ''Zwei'' ist kein gültiger Integer-Wert. Exception address: 0041EFB6 ------------------------------------------------------------------------------ Stack list, generated 28.08.2014 20:51:12 [0041EFB1]{Project1.exe} SysUtils.ConvertErrorFmt [0041FEF4]{Project1.exe} SysUtils.StrToInt [0087B2FD]{Project1.exe} Unit1.TForm1.Button1Click (Line 31, "Unit1.pas") [00497C6B]{Project1.exe} Controls.TControl.Click [004CD2FA]{Project1.exe} StdCtrls.TCustomButton.Click [004CDDE8]{Project1.exe} StdCtrls.TCustomButton.CNCommand [00497700]{Project1.exe} Controls.TControl.WndProc [0049BFC4]{Project1.exe} Controls.TWinControl.WndProc [004CCFC4]{Project1.exe} StdCtrls.TButtonControl.WndProc [00497324]{Project1.exe} Controls.TControl.Perform [0049C117]{Project1.exe} Controls.DoControlMsg [0049CB73]{Project1.exe} Controls.TWinControl.WMCommand [0050F428]{Project1.exe} Forms.TCustomForm.WMCommand [00497700]{Project1.exe} Controls.TControl.WndProc [0049C0C4]{Project1.exe} Controls.TWinControl.DefaultHandler [00497700]{Project1.exe} Controls.TControl.WndProc [0049BFC4]{Project1.exe} Controls.TWinControl.WndProc [0050C32C]{Project1.exe} Forms.TCustomForm.WndProc [00405DBC]{Project1.exe} System.TMonitor.Enter [00405C90]{Project1.exe} System.TMonitor.CheckOwningThread [00405F66]{Project1.exe} System.TMonitor.Exit [0049B664]{Project1.exe} Controls.TWinControl.MainWndProc [0045792C]{Project1.exe} Classes.StdWndProc [0049C0C4]{Project1.exe} Controls.TWinControl.DefaultHandler [004980BC]{Project1.exe} Controls.TControl.WMLButtonUp [00497700]{Project1.exe} Controls.TControl.WndProc [0049BFC4]{Project1.exe} Controls.TWinControl.WndProc [0049BBF3]{Project1.exe} Controls.TWinControl.WndProc [004061BE]{Project1.exe} System.TMonitor.TryEnter [00405DBC]{Project1.exe} System.TMonitor.Enter [00405C90]{Project1.exe} System.TMonitor.CheckOwningThread [00405F66]{Project1.exe} System.TMonitor.Exit [00405F9F]{Project1.exe} System.TMonitor.Exit [0047D543]{Project1.exe} Graphics.FreeMemoryContexts [0049B664]{Project1.exe} Controls.TWinControl.MainWndProc [0049B679]{Project1.exe} Controls.TWinControl.MainWndProc [0049B857]{Project1.exe} Controls.TWinControl.IsControlMouseMsg [0045792C]{Project1.exe} Classes.StdWndProc [0049BFC4]{Project1.exe} Controls.TWinControl.WndProc [00612599]{Project1.exe} dxHooks.TdxSystemHook.ProcessHookProcs [004CCFC4]{Project1.exe} StdCtrls.TButtonControl.WndProc [0049B664]{Project1.exe} Controls.TWinControl.MainWndProc [0045792C]{Project1.exe} Classes.StdWndProc [005152FB]{Project1.exe} Forms.TApplication.ProcessMessage [0051533E]{Project1.exe} Forms.TApplication.HandleMessage [00515669]{Project1.exe} Forms.TApplication.Run [00889959]{Project1.exe} Project1.Project1 (Line 13, "") ------------------------------------------------------------------------------ Active Controls hierarchy: TButton "Button1" TForm1 "Form1" Aber das sollte Deinen Ansprüchen erst mal genügen. Das tolle ist, es ist kostenlos. JCL installieren, Beispiel kompilieren und sehen wie es funktioniert. Dann einfach die für einen relevanten Teile in eine eigene Funktion extrahieren und fertig. Ach ja, wenn man "Debug DCUs" in dem Projekt Optionen aktiviert, gibt es zu jeder Zeile im Stack den Dateinamen und Zeilennummer :stupid: Ich hoffe das hilft Dir. MaBuSE [edit] Anmerkung: Wenn Du es nicht selbst programmieren möchtest, schau Dir mal madExcept an. ( ![]() Den Dialog kannst du auch abschalten und entsprechend die Infos im Code verwenden. [/edit] |
AW: aktuelle Quellcodezeile im Programm ermitteln
Zitat:
Für Delphi 7 gab es noch einen PreCompiler, welchen ein bekannter Typ (Andy) da reingehackt hatte, der sowas wie ![]() |
AW: aktuelle Quellcodezeile im Programm ermitteln
Zitat:
Da ich sowieso JCL im Einsatz habe, habe mich entschieden doch JCL zu verwenden und bin somit davon abgegangen den "System.AssertErrorProc" zu manipulieren, da vermutlich andere Asserts/Exceptions von anderen Units damit auch abgefangen werden. Nach einigen Experimenten funktioniert folgender Code für mein Vorhaben zufriedenstellend:
Delphi-Quellcode:
Achja, für Leute die eingehend sich mit den Möglichkeiten von JCL Debug beschäftigen möchten, weitere Beispiele findet man im JCL Installationsunterverzeichnis unter ".\examples\windows\debug". Der obige Code basiert in Prinzip auf JCL Beispiel ".\examples\windows\debug\sourceloc\SourceLocExamp le.dpr".
implementation
uses JclDebug; procedure LogMsg(Msg:String); var s: String; begin s := Format('%s:%u (%s) "%s"',[FileByLevel(1), LineByLevel(1), ProcByLevel(1), Msg]); WriteToLogFile(s); // <----- ist nur exemplarisch gemeint ;-) end; procedure TForm1.Button1Click(Sender: TObject); begin LogMsg('Fehlermeldung: Blablabla...'); end; Lg, jus |
AW: aktuelle Quellcodezeile im Programm ermitteln
Zitat:
Delphi-Quellcode:
Da kommt dann der Stack wie folgt raus:
...
// Form mit 1 x TButton + 1 x TMemo implementation uses jclDebug; {$R *.dfm} function GetStackList( IncludeModuleName: Boolean = False; IncludeAddressOffset: Boolean = False; IncludeStartProcLineOffset: Boolean = False; IncludeVAddress: Boolean = False): string; var sl: TStringList; begin sl := TStringList.Create; try with TJclStackInfoList.Create(True, 0, nil) do try Delete(0); // TJclStackInfoList Delete(0); // TJclStackInfoList Delete(0); // GetStackList AddToStrings(sl, IncludeModuleName, IncludeAddressOffset, IncludeStartProcLineOffset, IncludeVAddress); finally Free; end; Result := sl.Text; finally sl.Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin Memo1.Lines.Add(GetStackList); end; end.
Code:
[004DF643] Unit1.TForm1.Button1Click (Line 57, "Unit1.pas")
[00470E2B] Controls.TControl.Click (Line 7190, "Controls.pas") [0049BD52] StdCtrls.TCustomButton.Click (Line 4562, "StdCtrls.pas") [0049C840] StdCtrls.TCustomButton.CNCommand (Line 5023, "StdCtrls.pas") [004708C0] Controls.TControl.WndProc (Line 7074, "Controls.pas") [00475184] Controls.TWinControl.WndProc (Line 9831, "Controls.pas") ... |
AW: aktuelle Quellcodezeile im Programm ermitteln
Zitat:
[edit]dummerweise Zitat statt Bearbeiten gedrückt. sorry[/edit] |
AW: aktuelle Quellcodezeile im Programm ermitteln
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:50 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz