AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi aktuelle Quellcodezeile im Programm ermitteln
Thema durchsuchen
Ansicht
Themen-Optionen

aktuelle Quellcodezeile im Programm ermitteln

Ein Thema von jus · begonnen am 28. Aug 2014 · letzter Beitrag vom 29. Aug 2014
Antwort Antwort
Seite 1 von 2  1 2      
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#1

aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 18:13
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:
[2014-07-30 23:06:18.875] Programm Error - F:\relbranch-2_0\Adapter.cpp:309 - running failed with exception: System exception
Sprich da wird die aktuelle Codezeilennummer wie in diesem Fall Zeile "309" mit in das Programm einkompiliert. Kann man sowas in Delphi auch machen?

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

Geändert von jus (28. Aug 2014 um 18:18 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#2

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 18:15
Schau Dir mal Assertions an.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#3

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 19:13
Schau Dir mal Assertions an.
Vielen Dank DeddyH!

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:
  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;
Ich habe den obigen von "AssertErrorProc (Delphi)" genommen und ein wenig gekürzt.

Lg,
jus
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.590 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 20:22
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.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.840 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 20:59
Sprich da wird die aktuelle Codezeilennummer wie in diesem Fall Zeile "309" mit in das Programm einkompiliert. Kann man sowas in Delphi auch machen?
Ja das geht. Das wird aber nicht "reinkompiliert" sondern zur Laufzeit ermittelt.

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:
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  StrToInt('Zwei');
end;
...
Es kommt dann z.B. folgendes im Logfile an:
Code:
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"
Wir loggen noch viel viel mehr Informationen zu jedem Fehler.
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

Ich hoffe das hilft Dir.
MaBuSE

[edit]
Anmerkung:
Wenn Du es nicht selbst programmieren möchtest, schau Dir mal madExcept an. (http://www.madexcept.com/madExceptDescription.htm)
Den Dialog kannst du auch abschalten und entsprechend die Infos im Code verwenden.
[/edit]
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)

Geändert von MaBuSE (28. Aug 2014 um 21:10 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.081 Beiträge
 
Delphi 12 Athens
 
#6

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 22:45
Zitat:
Die JCL (JEDI Component Library) kann das zum Beispiel.
Eurekalog und Co. haben auch solche Funktionen, welche man selber verwenden kann.

Für Delphi 7 gab es noch einen PreCompiler, welchen ein bekannter Typ (Andy) da reingehackt hatte, der sowas wie __LINE__ im Delphi zur Verfügung stellte.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (28. Aug 2014 um 22:47 Uhr)
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#7

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 23:15
Die JCL (JEDI Component Library) kann das zum Beispiel.
@MaBuSE: Vielen vielen Dank für den Tipp!
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:
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;
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".

Lg,
jus

Geändert von jus (28. Aug 2014 um 23:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.840 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 23:37
Nach einigen Experimenten funktioniert folgender Code für mein Vorhaben zufriedenstellend
Wenn ich nur den Stack haben will mache ich folgendes:

Delphi-Quellcode:
...
// 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.
Da kommt dann der Stack wie folgt raus:
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")
...
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.840 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 28. Aug 2014, 23:41
Wenn ich nur den Stack haben will mache ich folgendes
Oft macht es Sinn zu wissen von wem bzw. wo meine Funktion aufgerufen wurde.

[edit]dummerweise Zitat statt Bearbeiten gedrückt. sorry[/edit]
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
jus

Registriert seit: 22. Jan 2005
344 Beiträge
 
Delphi 2007 Professional
 
#10

AW: aktuelle Quellcodezeile im Programm ermitteln

  Alt 29. Aug 2014, 16:44
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.
Oft macht es Sinn zu wissen von wem bzw. wo meine Funktion aufgerufen wurde.
@jaenicke und @MaBuSE: Vielen Dank für die Hinweise! Wieder mal was dazugelernt.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:58 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz