Forum > Debugger

[SOLVED] Minor Q: HowTo use 'DebugLn' in a DLL?

(1/4) > >>

d7_2_laz:
I'd oftenly used "OutputDebugString" for to trace some stuff, but sometimes there are situations where i couldn't use it (as it requires the "Windows" uses, and that's oftenly not appliable).
So i switched more and more to use "DebugLn", and for a stand-alone exe i do need to:
1. Main form: include "LazLogger" in the use clause
2. Project Options > Compiler Options > 'Config and Target':  'Win32 gui application (-WG)' => no
3. Run Parameters > Command line parameters :  --debug-log=<logfile_path_and_name>

The latter isn't possible when developing a plugin DLL. As - related to 3. - the "Host Application" exe of course will not understand this command line parameter resp. interpretes it in an unpredictable way.

Is there an equivalent for this Run parameter for a DLL?

PS: background is: in a plugin DLL, i had a problem with my docking form's toolbar that sometimes lost the trigger to be drawn and appeared empty. Occured when the host application opened a docked subdialog below my docking form, or, same, when i closed this docked subdialog. Toolbar buttons were not drawn anymore.
I found a workaround for this. But i'm still interested to see which layer maybe not passed a paint message to the toolbar (the OnPaintButtons callback won't be called in this case).

Martin_fr:
Well you need to use the unit LazLagger in the dll => that will initialize the logger instance.
Actually => assuming initialization sections are run. Not sure that happens in a dll.

So if initialization sections are not run, then you must at some point trigger the setup yourself

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  uses LazLoger; function CreateDebugLogger: TRefCountedObject;begin  Result := TLazLoggerFile.Create;//  TLazLoggerFile(Result).Assign(GetExistingDebugLogger);  // optional / if you call only once there should be none to copy any setting fromend; begin  LazDebugLoggerCreator := @CreateDebugLogger; 
Then the first call to  Debugln will call you creator, and the logger will be setup.

I don't know if the logger will be able to see the argc/argv in the dll. And even if, it may not be possible to give the relevant switches.

In that case your creator method can setup hardcoded settings.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---YourLazLoggerFile.LogName := 'log.txt';
Feel free to add it to the relevant wiki pages ;)

PascalDragon:

--- Quote from: d7_2_laz on January 20, 2025, 08:39:18 pm ---I'd oftenly used "OutputDebugString" for to trace some stuff, but sometimes there are situations where i couldn't use it (as it requires the "Windows" uses, and that's oftenly not appliable).
--- End quote ---

You can always import that function yourself by copying the declaration. The kernel32.dll is always loaded anyway.

d7_2_laz:
Hi Martin,
that sounds very good; i can try to elaborate tomorrow and come back with the result.

Some small remarks here:
- yes, the plugin's controlling unit has an initialization section as well as a finalization.
  Otherwise this shouldn't be a problem either by the method yoo describe. One could do it (LazDebugLoggerCreator := .. etc.) in FormCreate (or plugin's Create) too and that should be sufficient.
  As far as Lazarus internal units are concerned and it's about to trace back here in higher levels of the hierarchy why some callback might be _Not triggered_ (*).
- "if the logger will be able to see the argc/argv in the dll" -> in my case (plugin for NotePad++) the host application will eat up this argument (it tries to open it as file and claims, this cannot be opened).

(*) In this situation (Not triggered) the means of stacktrace, breakpoint & Co. are of limit help. Normally i don't have such situation and so i'm still a noob in the matters of DebugLn. That won't be sufficient for a wiki article.
But what I could contribute - if i should succeed - is a kind of summary 'from a noob perspective' as attached document, for any free usage.

Hi PascalDragon:,
"import that function": that could be, but i'm oftenly within diverse .inc files (and then their includers, and up) and feel, to manipulate here wouldn't be a preferred strategy and it would be better to use the native DebugLn.
(Import in the main unit / main form / plugin's pas file wouldn't be a problem. But here's the OutputDebugString already available anyway).

d7_2_laz:
Would the following procedure from a first test basically be correct?
'The first call to Debugln will call your creator' .. but it appears to me it's never entered.
I guess it still relies somehow on the command line param (resp. an env. variable).

The "LogName" property: might it contain a path particle?


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---interfaceuses ....,    LazLogger.    LazLoggerBase,   // needed for GetExistingDebugLogger    LazClasses;      // needed for TRefCountedObject function CreateDebugLogger: TRefCountedObject;begin  Result := TLazLoggerFile.Create;  //TLazLoggerFile(Result).Assign(GetExistingDebugLogger);  // optional / if you call only once there should be none to copy any setting from  //TLazLoggerFile(Result).LogName := '___aLogfile.txt';  TLazLoggerFile(Result).LogName := 'D:\test\___aLogfile.txt';  // With path, possible? Otherwise, what might be the default path?  outputdebugstring(pchar(' --- check: am i called? '));   // No output in the event log  // A breakpoint on any line in this function won't be entered.end; procedure TXYZDockingForm.FormCreate(Sender: TObject);var .....,  LazDebugLoggerCreator: TRefCountedObject;begin   LazDebugLoggerCreator := @CreateDebugLogger;   DebugLn(' ==== testTXYZDockingForm.FormCreate');  // ... the first call to Debugln will call your creator 

Navigation

[0] Message Index

[#] Next page

Go to full version