Delphi "EClassNotFound" errors, and corrupted DFM possibility - delphi

I am getting a cascading set of "EClassNotFound" errors in in my Delphi 2007 project. Doesn't seem to be caused by the missing Name property value as often is the case, and though adding RegisterClass(XXX) in the initialization section(s) fixes the EClassNotFound error at hand, another one follows it seemingly indefinitely.
I finally cracked open the DFM file in text editor, and it looks likely corrupted to me (lots of non-ASCII characters amidst form element names, and very "unstructured" looking when compared to what I'm used to seeing in a DFM file). (I'd post a same here but not sure that's OK, w/the non-aSCII, so will hold off).
The form loads fine, and seems to compile / syntax check OK too, but once I run it, trouble.
Going back to early versions of it in SVN, it looks like it's been in this state for some time, which makes me think that either A) the DFM file isn't my problem, or B) the Delphi form-streaming is quite fault-tolerant/robust (Bonus Question: Which is it?).
If the DFM file is the problem, and is corrupted, rolling back will have to be a roll-back WAY back, and that's gonna be expensive. Given that the IDE can still load it, is there any utility that can clean up the file?
Or, am I totally off base w/the DFM as primary suspect?
Thanks folks for the input. Forgot about the binary/text options w/DFM files, so that was helpful. It looks like the DFM itself is not corrupted.
Still having the EClassError issue though. re: It being missing property values, or referencing non-existing properties, etc., a further question: Is the class the error is given for (currently TnxSqlUpdateObject, but probably more waiting in the wings if experience thus far is consistent) usually/always the actual "culprit" class/object?
For instance, right now my main form has four references to TnxSqlUpdateObject, w/those actually dropped on the form. If I put RegisterClass(TnxSqlUpdateObject) in the initialization section, it runs fine for that EClassNotFound error but then goes on to the next one (in this case, TStringField).
I have reinstalled the NexusDB components in this case, and also built a new project using some of the components I thought might be the problem. It compiles and runs fine, UNTIL I add this other form from my real project (which, in turn, unfortunately references quite a few others).
SO, it sounds like my real issue is how to methodically diagnose and fix any and all EClassNotFound errors?

I get this error if a component is on the form, but doesn't have an entry in the form definition in the source file too. Most often when I've copied and pasted from another form. Simplest solution is to select the component, cut it, then paste it back. When you save, the component's unit will be added to the source, and when you run it again it will all be okay.

Well, a dfm file could be binary or tekst (as I'm correct from version 4.0).
You can check this by right click on the form and check the Text DFM flag.
If a dfm file is corrupt, tou can try to fix it by removing all suspicious lines.
Be sure to leave the object .. end sets intact and you probably only loose some property values.
By the way, the dfm file should look like this (to get an idea of the general structure):
object Form5: TForm5
Left = 0
DesignSize = (
426
652)
object Button1: TButton
Left = 343
end
object Memo2: TMemo
Anchors = [akLeft, akTop, akRight, akBottom]
end
end
If it does not look like that you are probably editing the binary file.

If you have a recent compiled exe that works, you can use a resource-editor, like PE Explorer, to get the dfm-definition. Then you can compare the one from the exe with the one that you now have.
I believe there is tools to convert binary dfm-files to text-files too. This will give you a better view on the file, and help you decide if it's really corrupted or not. I see Felix has something on the topic.
If the Delphi IDE shows the form ok without errors, I can't believe there is a corruption-error. Could there be a package problem? Do you use runtime-packages?
Update:
Hvae you tried Eurekalog or madExcept or something similar to get a more detailed error message with callstack and memorydumt? Maybe that will give you some clue about the problem.
But generally i think this error comes from missing runtime package, or a missing unit in the uses-clause. If you think you know witch component causes the error, search the source for the call to RegisterClass( ), and see if that unit somehow is included in the projcets uses-clause. If not, add it and try again.

If you can load the form in the Delphi IDE the DFM resource is not corrupted. Delphi uses the same code to load the DFM as the final executable will use, so I think that won't be the reason.
You can open the DFM in the Delphi IDE directly (if the corresponding pas file is not open), or you can use Alt+F12 to switch between form view and text view of the DFM. In this view the structure should be sane, with correct indentation and so on.
As Gamecat pointed out you can use the command in the form popup menu to toggle the DFM storage format. Leave it as text for Delphi 5+, it works better this way with SVN.
As for the cause of your runtime problem - I have no idea...
Edit: After your ruling out the DFM as the source of the problem I can only assume that an important unit in the uses list is missing, which can only happen if not all the components on your form have a corresponding member field. You should check that all the components referenced in the DFM are also in the form, even when you do not access them in your code. This will in turn cause Delphi to add any missing units to the uses clause when the file is saved. Manually registering components should not be necessary if the form class has references to all the components in the DFM.
For a quick check you could create a test form, drop all of the components that your "problem" form has onto it (one instance is enough), and check whether this works.

This can happen in case you have changed one of your custom components and removed a property from it. The property is stil in the DFM and Delphi tries to initialize it.
Try to remove manually parts from your DFM so you can pinpoint which component is causing the problem.

Try this:
Make backup first
Right click on form in designer; uncheck "Text DFM"
Save
Right click on form in designer; check "Text DFM"
Save

Related

Referencing a type from a package library in Delphi

I have inherited a legacy Delphi project for which I have to do a code modification. But to start with, I have problem compiling the project into a "correct" application. As I am not familiar with Delphi, I am not sure what is missing.
So far, the only changes I have done are around PATH for references and packages wherever I could find an absolute path that was different on my PC. It is compiling and running. However, one of the variable remains "incorrectly" initialized at run-time (value is nil). I am a bit surprised because I have not changed anything in the code, that is from an application otherwise running.
The type of this variable is defined in a package library (for which I have the code as well, that compiles, and that is in the list of "Packages" checked in the Project Options.
Some code sample:
Unit Unit3
interface
uses
VCLZ;
TFrmCCB = class(TForm)
vz: TVCLZ;
implementation
procedure TFrmCCB.FormCreate(Sender: TObject)
var
[...]
begin
vz.SetPath := 'C:\'; //at this point vz is nil
Do I have to add some code to get vz to not be nil, or does it look like a configuration problem with the definition not found at run time or something like that? I would seem strange that something is missing in the code though, as I have not done any change there yet and the program is otherwise running.
It sounds like vz: TVCLZ is a component on a form.
When you first open the form if you don't have the component (package) installed in the IDE it asks you if you want to remove the component (because the IDE doesn't know how to render/instantiate it at design-time). If you choose to remove it the code associated with that component remains.
So you remain with something similar to what you have. The form doesn't create the component at run-time (because it doesn't have it anymore) the vz member remains uninitialized.
So, you have to get the sources of the project with the component on the form and be careful not to delete it.
Or, you care create the instance yourself. At FormCreate just create it: vz := TVCLZ.Create(Self); before you use it. But keep in mind that all the properties set in design will be lost and you have to set them manually in code.

How to reproduce this Code Completion bug?

I'm having a bug on Delphi XE2 (Update 4 Hotfix 1), which reproduces many times on the legacy project I work (it evolved from D6 to D7,D2006 and finally XE2), but I didn't know how to trigger it in a smaller project.
The latest time, it triggered on creating an event handler for a "hidden popup" on the app. When I click on the menu option to create the Click handler this happens.
pprocedure TMainForm.Blablabla1Click(Sender: TObject);
begin
end;
rocedure TMainForm.FormActivate(Sender: TObject);
You can see that the IDE inserted the new code INSIDE the declaration of the next method... But it's not all.
Almost all times, on the DPR, code gets mangled too:
AApplication.CreateForm(TDM_DataAcc, DM_DataAcc);
AApplication.CreateForm(TMainForm, MainForm);
pplication.CreateForm(Tfrm_login, frm_login);
f frm_Login.CanLogin = mrOK then Application.Run
(It's almost like that, I don't remember if the 3rd Application.CreateForm get its' 'A' clipped or not, the other I'm sure are doubled and the IF gets its' "I" clipped).
Chasing on QualityCentral doesn't help (found nothing). This also happens sometimes on Class Completion(Ctrl-SHift-C).
Someone knows what triggers that bug, so I can create an new application and send it to Embarcadero?
Behavior like that suggests that the IDE is miscounting characters in the file. There are several "file oddities" that the developers might not have anticipated and that could cause a character index to be miscalculated.
Check your file for unusual line endings. For example, a line missing a carriage return will appear correctly in the editor, but can cause incorrect line numbers elsewhere in the program.
Non-breaking spaces are another kind of character that will appear normally, and maybe even parse correctly, but occupies multiple bytes when represented in UTF-8 when the "normal" version of the character (a regular space) only takes up one. You will sometimes acquire such characters if you copy code from a Web browser.
Incorrect byte-order marks for UTF-8 or UTF-16 source files might also cause problems.
Often, opening your source file in Notepad or a hex editor will help you identify these problems.

Lazarus Free Pascal / Delphi - RunError 211

I'm trying to connect my Windows XP program (Lazarus) to my Ubuntu postgres server.
When the Lazarus program runs, it seems to compile fine but I get this error:
Project ... raised exception class 'RunError(211)'.
Then it terminates execution (and I don't see any output), and opens up a file customform.inc. In that file, it shows a procedure procedure TCustomForm.DoCreate; where it highlights a line: if Assigned(FOnCreate) then FOnCreate(Self);
I believe this is one of the system's files.
I never get to see any output.
What could this be? Thanks!
MORE INFO:
I've narrowed down the error to this line:
dbQuery_Menu.SQL.Text:='Select * From "tblMenus"';
dbQuery_Menu.Open;
the exception is triggered when the OPEN statement gets executed.
BTW, dbQuery_Menu is defined as a TSQLQuery component.
Clueless! :(
Run error 211 appears when you try to call an abstract method. Check this link from more information on FreePascal/Lazarus runtime errors.
Since you say all is done by code and you have no visual components, the problem probably lies in your code trying to use an ancestor component which has not overriden the Open method. You should be able to solve this by using the correct descendant component.
Another possibility, although I would strongly recommend to avoid this one, is to override the Open method yourself. It should be avoided because if you are using an ancestor component then you probably would have to override more abstract methods.
HTH
After nearly 5 days I found the answer. Many thanks to all thos e ho have contributed with their ideas ESPECIALLY RRUZ, RBA and Guillem Vicens. there are other related posts all connected to getting the FIRST Lazarus program working with PostgreSQL.
Summary.
The biggest mistake I made here was that I used the TSQLConnection component. Don't do this. Instead use the TPQConnection.
Everything is done through code. We're not using any draggable components from the top tab.
Don't rely on the Lazarus docs (wiki) at least for working with PG DBs.. It is outdated. Some of the examples can be pretty misleading.
Make sure that fields have some default values. For example, if a Boolean field has no true or false (t/f) set, this may lead to errors.
And that's it! I hope many postgres+Lazarus newbies will find this useful.
From here - http://www.network-theory.co.uk/docs/postgresql9/vol2/SQLSTATEvsSQLCODE.html - -211 (ECPG_CONVERT_BOOL) This means the host variable is of type bool and the datum in the database is neither 't' nor 'f'. (SQLSTATE 42804)

GExpert's Replace Components Expert doesn't replace the text in the form file (*.dfm)

I am using Delphi 2010 and GExperts stable release 1.35
I am testing the "Replace Components" expert.
I add a main form and a secondary form. Each has three TEdits on it.
I use the Replace Components Expert to replace all TEdits with TRzEdit. I Check the Replace all components on all forms of the project.
It works, it replaces them all. However, it doesn't do anything to the DFM file. How do i make it replace those instances.
If i save, compile, or rebuild, i get errors.
If i try to view the form as text after replacing, i get errors.
Can someone explain to me the steps to make this work?
Thanks
I just tried it with Delphi XE and GExperts 1.35 and it does indeed crash now even after a single "Replace Selected". (It used to work fine in the past).
It seems that using the hidden menu Project | Clear Unit Cache just after Replace Components then doing a full build before trying any Save/Compile/View As Text... fixes the problem.
I think this menu is surfaced with cnPack. I don't have it and cannot guarantee, but you can easily do it yourself by adding the following unit in one of your installed packages:
unit FGEnableHiddenMenus;
interface
procedure Register;
implementation
uses
Classes, Forms, Menus;
procedure Register;
var
Comp: TComponent;
begin
//Make a hidden menu item visible
Comp := Application.MainForm.FindComponent('ProjectClearUnitCacheItem');
if Comp is TMenuItem then
TMenuItem(Comp).Visible := True;
end;
end.
Source: Brian Long's old goodies
Update:
I had to replace a couple of TEdit by TDBEdit on our main project at work and this trick worked.
But on a new Project with 3 Forms, it failed consistently to write/commit/save the changes on the last Form (same environment).
FYI, I tried with and without DDevExtensions 2.5 and IDEFixPack 4.6.1
Update2:
Went digging in the GExperts forum as suggested by Ulrich and finally found a possible explanation. The new property Touch does not like being copied from one component to another when the source is destroyed (causing the AV).
The suggested workaround is to do a bidirectional mapping in the Expert Settings to disable the copy for this property:
You might be running into this bug while trying to copy the Touch property from the old to the new component, but it has a workaround you can fairly easily test:
http://tech.groups.yahoo.com/group/GExpertsDiscuss/message/3994
Details:
There is a limitation/bug in Delphi 2010 and XE where if you assign a
Component.Touch property from one component to another and destroy the
original component that the new component becomes corrupt (it isn't
like component/interface references, where they either auto-correct
themselves or are reference counted).
For the moment, you can assign a bi-directional replace component
property map from TPanel.Touch to TGroupBox.Touch (use the two components being replaced in your specific case) that is marked as
a disabled property map, and that will work around this problem. Our next release
will not try to assign that property any longer.
GExperts 1.36 is also now available and includes a workaround for this issue. The workaround has been in the GExperts version control system and in testing for several weeks already.

Form Designer Save and Load

i made a simple form designer in delphi, drag and drop a button on the form and it draws it, but the thing is i cant save/load this project since i dunno how to, is there anyway that i could be abel to save it to .rc file and load it from there?
That depends how you programmed your form designer. In forms created in Delphi's designer all components (and subcomponents) are referenced from TForm.Components array property. All controls are also referenced in TForm.Controls array property (if you remove an container control, all it's subcontrols are destroyed too).
If you have followed that pattern, all you have to do is monitor additions to the TForm.Components array (maybe using an overriden TForm.Notification method) and using this data to build your persistent form's file.
The VCL contains methods for using its builtin DFM support. There is a sample in the Delphi 2009 documentation for ObjectBinaryToText; I guess this works for D7 too. And IIRC there already was a code fragment for ComponentToString in the D5 help - search for ObjectBinaryToText.
Delphi stores form layout in *.dfm file. You can use it's structure to save your projects. File is textual and readable by humans. It is not hard to parse file like that rading one line by one. If you need more help, ask for it.
You can use something like delphi .DFM. Counting all objects and then read their attributes and write them into a file. Example Code:
For i:0 To Form1.ComponentsCount-1 Do Begin
// Read Component Attributes And Write Them In Your Format
End;
If you just want to save the form you designed in your designer, use something like TFileStream to create the RC file when the user saves. You might be better off with your own file format for your forms, with the option to export as an RC file, as RC files arent really meant to useful for storing any design time info you may need.

Resources