Eklatante Probleme mit Debuggen
Hallo zusammen,
wir (ca. 10 Entwickler) haben seit Jahren Probleme mit dem Debuggen, seit einiger Zeit sind diese eklatant. Es äußert sich so, dass der Debugger bei Breakpoints nicht mehr anhält. (Auch gibt es keine blauen Punkte.) Das Problem tritt nicht immer auf. Es gibt jedoch bestimmte Packages, bei denen es in 98% der Fälle so ist. Wir behelfen uns dann mit Logging über CodeSite, das ist jedoch Programmieren wie vor 30 Jahren. Das Problem in einem abgegrenzten Umfeld zu reproduzieren ist uns noch nicht gelungen. Wir arbeiten derzeit mit 64-Bit, Delphi 11.3, es gibt mehr als 100 Module und mehrer Millionen Zeilen Quellcode. Wir haben inzwischen ein umfangreiches internes Dokument mit Anleitungen was man alles versuchen kann, damit das Debuggen geht. (Build nur als Release und nur benötigte Module mit Debug, Löschen von rsm-Dateien, Delphi neu starten, Option "Load all Symbols" aus und Module explizit angeben, anderes Startprojekt, etc. ...). Das hilft oft nach einigen Versuchen, ist aber extrem hinderlich. Und bei dem oben erwähnten Modulen hilft es eben gar nicht. EMB ist leider auch nicht sehr hilfreich. Der Support hatte einen Fall mal analysiert und einen Workaround (anderes Startprojekt). Ein Fehler in einem Log wurde nicht weiter thematisiert. Der Support weigert sich ausserdem bei uns per Videotool reinzuschauen - aus irgendwelchen datenschutzrechtlichen Gründen. Ohne ein konkretes reproduzierbares Problem ist auch nicht etwas zu erwarten. Marco Cantu und David Millington wissen Bescheid. Es wurde mal geschrieben, dass Verbesserungen beim Debugger in einer nicht näher spezifizierte Zukunft angestrebt seien. Weitere Hilfeanfragen blieben unbeantwortet. Habt Ihr noch eine Idee was wir da machen könnten? In der Zwischenzeit rate ich davon ab Delphi für neue unternehmenskritische Projekte zu verwenden. Es geht zwar wohl meistens gut, wenn man aber in diese Situation kommt, wird es kritisch. |
AW: Eklatante Probleme mit Debuggen
Ein Bekannter hatte ebenfalls einige Probleme beim Debuggen. Auch da fehlt immer wieder der Zugriff auf die Debuginformationen, so dass er keine Haltepunkte setzen kann usw., was sich also ähnlich anhört.
Meine Idee war, den Remote Debugger zu verwenden. Das hat dann auch geklappt. Da ließen sich die Haltepunkte normal setzen, debuggen, alles lief. Sprich er hat einfach lokal den Remote Debugger gestartet und verwendet dann "Prozess laden" mit 127.0.0.1 als Host zum Debuggen. Das ist zwar nicht ideal, funktioniert bei ihm aber deutlich besser als direkt mit dem Debugger. |
AW: Eklatante Probleme mit Debuggen
Zitat:
Bis bald... Thomas |
AW: Eklatante Probleme mit Debuggen
Wobei bei Win64 doch intern eigentlich sowieso der RemoteDebugger benutzt wird. :gruebel:
|
AW: Eklatante Probleme mit Debuggen
Gut, in dem Fall war es 32-Bit. Ob es bei 64-Bit einen Unterschied macht, weiß ich nicht.
|
AW: Eklatante Probleme mit Debuggen
Was für mich gut funktioniert in solchen Fällen ist den Debugger erst *nach* Programmstart mit dem Programm zu verbinden (Run-> Attach To Process). Ggf muss man im Programm eine Messagebox einbauen damit das Programm absichtlich anhält und man die Zeit hat, den Debugger zu verbinden.
|
AW: Eklatante Probleme mit Debuggen
Zitat:
Delphi-Quellcode:
Das funktioniert auch bei Diensten.
while not IsDebuggerPresent do
Sleep(10); |
AW: Eklatante Probleme mit Debuggen
Zitat:
|
AW: Eklatante Probleme mit Debuggen
Das ist natürlich richtig, aber wenn man alle Änderungen überprüft und z.B. vor und nachher ein paar Leerzeilen und/oder eine Compilerwarnung einfügt, kann das kaum passieren.
Im Dienst fällt mir z.B. gar keine andere sinnvolle Variante ein, wenn man den Start des Dienstes debuggen möchte. |
AW: Eklatante Probleme mit Debuggen
Da der normale Code des TService sofort wieder stoppt, wenn das Programm nicht aus dem Service-Host gestartet wird, hatte ich den Code mal etwas nachgebaut.
Dann noch ein kleines Dummy-Fenster, damit man den Dienst "sieht" und was Einfaches zum Beenden hat. Somit lässt es sich auch einfach über Debugger oder normals starten. (beim Kunden auch mal "manuell" und mit einigen Logausgaben im Consolenfenster, falls es dort mal wieder Probleme beim Starten gibt) Wenn nur über Debugger, dann ginge auch IsDebuggerPresent, aber hier einfach mit einem Parameter gelöst, damit es auch einzeln starten kann. Das TService vom Windows ist eh etwas "beschränkt". z.B. läßt sich der Dienst nur einmal registrieren&installieren (außer man schmuggelt z.B. noch einen Start-Parameter mit rein) |
AW: Eklatante Probleme mit Debuggen
Beim Service gibt es doch diesen DDService, der noch mehr Methoden als TService implementiert, den kann man auch debuggen...
|
AW: Eklatante Probleme mit Debuggen
Ist jetzt schon über 10 Jahre her, aber im Grunde ging es darauf hinaus, jenes SvcMgr.Application.Run nachzubauen, damit es eben nicht mehr abbricht, wenn nicht als Dienst gestartet.
Falls ich nichts vergessen oder zu viel rausgelöscht habe. ServiceExecute läuft eigentlich in einem Thread und könnte man dort noch ein CreateAnonymusThread drumrummachen, aber hatte ich mir zum einfacheren Debuggen damals erspart.
Delphi-Quellcode:
Kurzfassung:
procedure TMyService.ServiceCreate(Sender: TObject); // TService.OnCreate
var Started: Boolean; DebugWindow: TForm; begin FIsDebugging := IsDebuggerPresent or FindCmdLineSwitch('DEBUG', ['-', '/'], True); // Das war der Teil, damit es sich mit der Console verbindet und man dann einfach z.B. via WriteLn('log message'); was ausgeben kann. // Oder z.B. noch ein Memo ins DebugWindow. // Gebe in die Console, sowie ins Windows-EreignisLog, eh nur wichtigsten Stati aus, damit der Admin vor Ort einen Überblick bekommt (der Rest in normale Logdateien) if FIsDebugging then AttachConsole(ATTACH_PARENT_PROCESS); try if FIsDebugging then begin MyService := Self; // wird sonst von Application.CreateForm gesetzt, aber durch die Messageloop kommt es dort nicht vorbei Forms.Application.MainFormOnTaskBar := False; // geht leider doch nicht ohne Form Forms.Application.CreateForm(TForm, DebugWindow); // Form zum Beenden und für Eintrag in Taskbar DebugWindow.Name := 'DebugWindow'; DebugWindow.Caption := 'Debug-Mode: ' + DM1.DSDisplayName + GenerateViewID(True); DebugWindow.OnCloseQuery := DebugServiceClose; DebugWindow.Width := 500; DebugWindow.Height := 125; DebugWindow.Visible := True; with TButton.Create(DebugWindow) do begin Name := 'DebugWindowsClose'; Parent := DebugWindow; Caption := 'Close'; Width := 100; OnClick := DebugServiceClose2; end; { SvcMgr.Application.Run; // bricht ab, wenn nicht als Service gestartet, darum dessen Code hier nachgebaut } if FindCmdLineSwitch('INSTALL', ['-', '/'], True) then begin TServiceApplicationAccess(SvcMgr.Application).RegisterServices(True, FindCmdLineSwitch('SILENT', ['-', '/'], True)); end else if FindCmdLineSwitch('UNINSTALL', ['-', '/'], True) then begin TServiceApplicationAccess(SvcMgr.Application).RegisterServices(False, FindCmdLineSwitch('SILENT', ['-', '/'], True)); end else begin Started := True; ServiceStart(Self, Started); if Started then begin ServiceExecute(nil); // der Service-Thread existiert/läuft nicht, wenn die EXE nicht aus der Service-Verwaltung gestartet wurde, daher manueller Aufruf, um die BackgroundThreads zu starten while not Terminated and not Forms.Application.Terminated do try Forms.Application.ProcessMessages; Sleep(10); except {error logging ...} end; Forms.Application.Terminate; for i := 1 to 30 do begin // Bissl warten, damit sich die BackgroundThreads sich noch rechtzeitig beenden können. (DebugWindow.FindComponent('DebugWindowsClose') as TButton).Caption := Format('Terminate (%ds)', [31 - i]); Forms.Application.ProcessMessages; Sleep(1*MSecsPerSec); end; try DebugWindow.Free; except end; end else begin Forms.Application.Terminate; end; end; end; except on E: Exception do begin if ExitCode = 0 then ExitCode := 38; // Fehlercode für IF ERRORLEVEL im aufrufenden Batch raise; end; end; end; procedure TMyService.DebugServiceClose(Sender: TObject; var CanClose: Boolean); begin if not Forms.Application.Terminated then DebugServiceClose2((Sender as TForm).FindComponent('DebugWindowsClose')); end; procedure TMyService.DebugServiceClose2(Sender: TObject); begin if not ContainsText(TButton(Sender).Caption, 'Terminate') then begin //if Assigned(MyService) then // MyService.Terminate; // hier gibt es zwar ein Terminated, aber kein Terminate -> Status wird aus ServiceThread.Terminated geholt if Assigned(MyService) and Assigned(MyService.ServiceThread) then MyService.ServiceThread.Terminate; // eigentlich aktuell nicht nötig, da im Debugmodus der Service-Thread nicht existiert/läuft -> siehe ServiceExecute(nil); Forms.Application.Terminate; TButton(Sender).Caption := 'Terminate (30s)'; end else begin // Wenn der Apps nicht auf Terminate hören will, dann eben die harte Tour. (beim zweiten Klicken auf Close) TerminateProcess(GetCurrentProcess, 1); // Halt() versucht noch die Units zu entladen, wobei es hängen bleiben kann. Halt(1); end; end;
Delphi-Quellcode:
procedure TMyService.ServiceCreate(Sender: TObject); // TService.OnCreate
begin if IsDebuggerPresent or FindCmdLineSwitch('DEBUG', ['-', '/'], True) then begin MyService := Self; // wird sonst von Application.CreateForm gesetzt, aber durch die MessageLoop kommt es dort nicht vorbei { wie SvcMgr.Application.Run; } if FindCmdLineSwitch('INSTALL', ['-', '/'], True) then TServiceApplicationAccess(SvcMgr.Application).RegisterServices(True, FindCmdLineSwitch('SILENT', ['-', '/'], True)) else if FindCmdLineSwitch('UNINSTALL', ['-', '/'], True) then begin TServiceApplicationAccess(SvcMgr.Application).RegisterServices(False, FindCmdLineSwitch('SILENT', ['-', '/'], True)) else begin Started := True; ServiceStart(Self, Started); if Started then begin ServiceExecute(nil); while not Terminated and not Forms.Application.Terminated do // allerdings wird die Schleife ohne TForm sich eventuell vorzeitig beenden try Forms.Application.ProcessMessages; Sleep(10); except {error logging ...} end; Forms.Application.Terminate; end else Forms.Application.Terminate; end; end; end; |
AW: Eklatante Probleme mit Debuggen
Ich habe das mit dem Dienst auch mal gemacht, indem ich einfach geschaut habe, ob die Exe von der services.exe gestartet wurde. Wenn nicht, wurde ein Formular angezeigt, mit dem man den Installationsstatus sehen konnte und den Dienst auch z.B. installieren konnte.
Leider verhält sich aber ein Dienst nicht immer genauso, weshalb ich das Warten eingebaut habe, bis der Debugger dran hängt. Aber das ist hier ja nicht das Thema. |
AW: Eklatante Probleme mit Debuggen
Habe jetzt mal einen Test gemacht mit dem Attach. Also
* Delphi ist offen * App ausserhalb gestartet * In Delphi Run/Attach to Process * Process aus der Liste ausgewählt (1) * Attach * App stoppt im Debugger irgendwo, CPU-Fenster * F9 * Bediene die App entsprechend. Allerdings kein Halt am Breakpoint, blaue Punkte sind auch nicht da. Zu 1: dort ist das substituierte Laufwerk angezeigt sondern die Quelle, ist das ein Problem? |
AW: Eklatante Probleme mit Debuggen
Im DebuggerLog, da müsste irgendwo ein "Lade Modul" zu finden sein, mit dem Namen deiner EXE .... wie sieht diese Zeile aus?
|
AW: Eklatante Probleme mit Debuggen
Habe das Logging aktiviert und habe nun drei Dateien. Nur in der dbk_16380.log finde ich den App-Namen. Er kommt häufig vor. Erster Eintrag ist (anonymisiert):
[20412: 61620 ] [71] 7648 52D:\Project\40_20244\appfolder\sysWin64\AppName.e xe [CL=00000000] In keiner Zeile ist der substituierte Laufwerk. Habe nun im Log gesucht nach der unit wo ich einen Breakpoint gesetzt habe: [13812: 28099 ] UNVER bkPt 2713d70 (J:\appfolder\_dev\src\_Domain.Bereich\lala.lu.Dom ain.Bereich.Impl.pas 3302) isVer 0 isInv 0 nLoc 0 [CL=00000000] Dort ist das Laufwerk drin. |
AW: Eklatante Probleme mit Debuggen
Hast du externe Debugsymbole aktuell aktiviert? Verwendest du eine Projektgruppe?
Eventuell könnte der Process Monitor helfen, falls der Debugger die Debuginformationen an der falschen Stelle sucht. Bisher konnte ich solche Probleme aber vorher schon lösen, so dass ich mir das bisher nie anschauen musste. Ich weiß also nicht, ob dort falsche Dateizugriffe auftauchen könnten oder ähnliches. Einen Versuch wäre es wert. |
AW: Eklatante Probleme mit Debuggen
Hallo,
wir waren jetzt zu dritt einige Stunden dran und vieles (wieder einmal) ausprobiert Was meinst Du mit Debugsymbole. Die dcp oder rsm? Bei 64-Bit werden immer rsm-Dateien erzeugt egal ob die Option "Include remote debug symbols" an oder aus ist. Sie ist aber an. Process Monitor: 1. die bpl werden geladen von J: (subst) 2. (nur) die rsm von der Hauptexe wird geladen von D: 3. es gibt zig CreateFile "C:\DevTools\Embarcadero\Studio\22.0\bin\<UNKNOWN> .rsm" Diese "<UNKNOWN>" sieht man auch im Toolwindow Modules Bei einem Kollegen funktioniert das Attachen so auch und ein Breakpoint von ihm, der auch sonst funktionierte, hat auch damit funktioniert. Und die Stelle die bei mir nie funktioniert bei ihm auch nicht. Und die "<UNKNOWN>" hat er auch, obwohl es bei ihm funktionierte. |
AW: Eklatante Probleme mit Debuggen
Was heißt denn eigentlich "substituierte Laufwerk"? Hab jetzt nicht den ganzen Faden hier vor Augen, falls schon beantwortet.
Ist das eine RAM-Disk-Laufwerk oder ein zugewiesener Buchstabe für ein Netzlaufwerk (z.B. \\EuerPfadZumNetzlaufwerk\BeliebigerUnterordner)? |
AW: Eklatante Probleme mit Debuggen
Mit dem subst Befehl
c:\>subst J:\: => D:\Project\40_20244 |
AW: Eklatante Probleme mit Debuggen
Vor allem GIT und auch ab und an Windows machen manchmal komische Dinge und Lösen die Umleitung auf, obwohl es eigentlich nicht sein sollte.
Aber hierfür egal, da der Pfad ja so oder so stimmt. Nur sowas wie IDE/Programm/Batch als Admin starten, streikt erstmal, weil das SUBST-Laufwerk im anderen Account womöglich nicht da ist. Auch Links auf Desktop oder in Startleiste sind krank, weil z.B. der TerminalServer auf die kranke Idee kommt und nach dem Neustart standarmäßig "kaputte" Links wortlos löscht. (zu dem Zeitpunkt ist das Substlaufwerk aber noch nicht da) aber Debuggen geht eigentlich .... hier nur wegen anderen (eigenen) Dingen probleme. |
AW: Eklatante Probleme mit Debuggen
Mit subst gab es beim Debuggen und bei dateibasierten Datenbanken immer wieder mal Probleme. Da ist eine eigene Partition sinnvoller (falls es um einen definierten Pfad bei jedem Entwickler geht), alternativ funktioniert auch eine NTFS Junction gut (wenn man zwischen Verzeichnissen wechseln möchte). Von subst kann ich wirklich nur abraten.
|
AW: Eklatante Probleme mit Debuggen
Danke für den Tipp. Das "alternativ" irritiert mich etwas. Eine eigene Partition braucht man doch auf jedenfall. Die Junction ware dann ja "optional".
Ich habe das nun auch mit einer Junction gemacht, weil Windows mich die vorhandene Partition nicht genugend verkleinern lies. Die Partition hat jetzt nur ca. 10MB und den Laufwerksbuchstaben bekommen. Da ist nun die Junction drin. Bei dem Erfolg bin ich mir nicht ganz sicher. Nach der ersten Aktion hat das Debuggen auf Anhieb funktioniert bei den betroffenen Packages. Später ging es dann mal wieder nicht, lies sich aber durch die oben bereits erwähnten Aktionen wieder hin bekommen. Jetzt nach einigen Tagen bin ich nun vorsichtig optimistische dass diese Packages nun nicht mehr in die Kategorie "es hilft gar nichts" gehören sondern in die übliche Kategorie "man bekommt es mit viel Aufwand irgendwie hin". :dance::dance::dance::dance::dance::dance: Danke Euch allen und speziell an Sebastian:!:Sebastian :love::love::love::love: Und Richtung EMB: :evil::wall: |
AW: Eklatante Probleme mit Debuggen
Partitition oder Netzlaufwerk braucht man nicht immer.
Außerdem gibt es mehrere Wege (mehr als 3), um eine Partition oder eventuell auch ein Verzeichnis (auf Festplatte oder im Netzwerk) in einen Laufwerksbuchstaben oder ein Unterverzeichnis zu mappen. |
AW: Eklatante Probleme mit Debuggen
Und was wäre der vierte und weitere Weg um einen Laufwerskbuchstaben zu mappen neben Partition, Netzwerklaufwerk und Subst? (Ein Unterverzeichnis zu mappen ist hier kein Thema.)
Und inwieweit könnte das helfen um die Debugprobleme zu lindern? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:30 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