I just spent two weeks tracking down an error that very easily, could have been avoided, if I hadn't been in such a rush.
I'm creating an FMX desktop application using Delphi 11.3 professional and a SQLite database which targets Windows and MacOS. I'm using a
static class called TAppInfo which holds
constants,
variables,
procedures, and
functions for managing all the housekeeping bits for my application.
Inside the
class constructor I'm using
TPath.GetHomePath for managing paths:
//----------------------------------------------------------------------- // Build user paths //----------------------------------------------------------------------- ProgDataPath := IncludeTrailingPathDelimiter( TPath.GetHomePath) + VendorName + PathDelim + AppName;Database := ProgDataPath + PathDelim + DatabaseName;This works great. It allows me to test both
Windows and
MacOS. In addition, I can easily test this on
non-development machines by making sure I put the SQLite database file in the corresponding
Application Path. It lets me simulate how everything would work if the application had been installed using an installer.
Everything had been going great.
Build a little code.
Test on Windows (my development machine).
Test on MacOS using PAServer.
Test on a non-development Windows machine using a thumb drive.
All is good.
And then
BOOM!
It stopped working on the non-development test machine.
I kept getting a FireDAC SQLite error.
I couldn't figure out why
all of the sudden it just crashed when I tried running it on a test machine. I spent hours creating MAP files, and testing, and asking ChatGPT to help me troubleshoot.
I wrapped
exception logic inside OnCreate event handlers.
Nothing.
Same error without displaying the
exception logic.
"I may not be the brightest bulb on the tree..."
I may not be the brightest bulb on the tree but I knew something was different. I just couldn't figure it out
or remember what I did that was different. By now two weeks has gone by and no resolution.
This morning I stripped out all the
exception code and went back to square one. I looked at the project source. The only three units listed are two data modules and the main program.
begin Application.Initialize; Application.CreateForm(TdmImages, dmImages); Application.CreateForm(TdmSQLite, dmSQLite); Application.CreateForm(TfMain, fMain); Application.Run;end.
- There's nothing SQLite related in the dmImages data module.
- It's not getting to fMain.
- It must be dmSQLite.
It's doesn't make sense. I've got
exception logic inside the OnCreate event handler of dmSQLite but it's not firing off.
And then I had an
A-Ha! moment.
Right click on the dmSQLite data module and view as text!
Then I remembered what happened!
And there it was. The TFDConnection had
hardcoded Params.Strings with the Database configured to a file located on my
development machine and the DriverID = to
SQLite.
Then I remembered what happened. I had been creating a new
FastReport within the
IDE. The report needed data from the
SQLite database. So, I configured the TFDConnection to point to the SQLite database so I could drag and drop the database columns onto the report from within the
IDE.
Everything worked great! The report was spot on! I spent three days tweaking the report until it looked just right. I couldn't wait to test it on the non-development machine.
Ooops! I was in such a rush, I forgot to remove the hardcoded Params.Strings
I asked ChatGPT for an explanation as to why the OnCreate
exception logic didn't fire.
Explanation from ChatGPT:
- Delphi loads the .dfm or .fmx file and instantiates all the components declared within it.
- This includes setting all published properties like FDConnection.Params, FDQuery1.Connection, Button1.text, etc.
- This happens before the OnCreate event fires.
- After all components are created and their published properties are set, OnCreate is triggered.
? Your Specific Case
If TFDConnection.Params had hardcoded values (e.g. a file path or server name that doesn't exist on the test machine), they were already applied
before OnCreate — meaning the connection could already try to
auto-connect or be used by another component, causing a crash.
Lessons Learnt:- 80 miles an hour is faster than 100 miles an hour. When you rush you make mistakes.
- Published Properties inside .dfm and .fmx files are set before any corresponding OnCreate event handlers.
- Make it a priority to View forms and data modules as text when troubleshooting.
- Remember Occams Razor: "The simplest explanation is usually the best one."
Enjoy,
Semper Fi
Gunny Mike
https://zilchworks.com
Weiterlesen...