Delphi中的“EClassNotFound”错误和DFM文件损坏可能性

4
我在我的Delphi 2007项目中遇到了一系列"EClassNotFound"错误。这似乎不是由于缺少Name属性值所致,虽然在初始化部分添加RegisterClass(XXX)可以解决当前的EClassNotFound错误问题,但另一个错误随之而来,看起来是无限的。
最终我打开了DFM文件,在文本编辑器中查看,我认为它很可能已经损坏了(在表单元素名称中有许多非ASCII字符,并且与我习惯看到的DFM文件相比非常“不规则”)。表单加载正常,似乎也能编译/语法检查通过,但一旦运行就出现问题。
回到它在SVN的早期版本,看起来它已经处于这种状态有一段时间了,这让我想到要么A)DFM文件不是我的问题,要么B)Delphi表单流式传输非常容错/健壮(奖励问题:哪个是正确的?)。
如果DFM文件是问题,并且已经损坏,则回滚将不得不回滚到以前的版本,这将是代价高昂的。鉴于IDE仍然可以加载它,是否有任何实用程序可以清理文件?
或者,我完全没有正确猜测DFM是主要嫌疑人吗?
谢谢大家的帮助。我忘记了DFM文件的二进制/文本选项,所以这很有帮助。看起来DFM本身并没有损坏。
但是仍然存在EClassError问题。关于它是否缺少属性值或引用不存在的属性等问题,进一步的问题是:给出错误的类(当前为TnxSqlUpdateObject,但如果经验一致,可能还有更多待解决)通常/总是实际的“罪魁祸首”类/对象吗?
例如,现在我的主表单有四个对TnxSqlUpdateObject的引用,并且这些引用实际上已经放在了表单上。如果我将RegisterClass(TnxSqlUpdateObject)放在初始化部分,则它可以解决EClassNotFound错误,但随后会出现下一个错误(在这种情况下是TStringField)。
我已经重新安装了NexusDB组件,并构建了一个使用我认为可能是问题的某些组件的新项目。它编译和运行良好,直到我添加来自我的真实项目的另一个表单(反过来,不幸的是引用了相当多的其他表单)。
因此,我的真正问题是如何系统地诊断和修复任何和所有的EClassNotFound错误?

你是否使用packages-setting检查了你的构建?使用filemon并检查哪些外部文件被引用了。 - Vegar
6个回答

16

如果一个组件在表单上,但在源文件的表单定义中没有条目,则会出现此错误。这种情况通常出现在我从另一个表单复制和粘贴的时候。最简单的解决方法是选择该组件,剪切它,然后再粘贴回来。当您保存时,该组件的单位将被添加到源中,当您再次运行它时就会没问题了。


1
如果在所有组件声明之前加上“public”关键字,Delphi也无法找到这些条目。 - Vegar

2
如果你能在Delphi IDE中加载表单,那么DFM资源不会被损坏。Delphi使用与最终可执行文件相同的代码来加载DFM,所以我认为这不会是原因。
你可以直接在Delphi IDE中打开DFM(如果对应的pas文件没有打开),或者使用Alt+F12在DFM的表单视图和文本视图之间切换。在此视图中,结构应该是健全的,并且缩进等都是正确的。
正如Gamecat指出的那样,你可以使用表单弹出菜单中的命令来切换DFM存储格式。对于Delphi 5+,保持为文本格式,这样在SVN上效果更好。
至于你的运行时问题的原因——我不知道...... 编辑: 在排除DFM作为问题源后,我只能假设使用列表中缺少了一个重要的单元,只有当你的表单上的所有组件都有相应的成员字段时才会发生这种情况。你应该检查DFM中引用的所有组件是否也在表单中,即使你在代码中没有访问它们。这将导致Delphi在保存文件时添加任何缺失的单元到uses子句中。如果表单类对DFM中的所有组件都有引用,则不需要手动注册组件。
为了快速检查,你可以创建一个测试表单,将你的“问题”表单上的所有组件放到其中(一个实例就足够了),并检查它是否有效。

完全赞同 SVN(任何版本控制)部分。二进制源代码非常糟糕的版本控制。 - Toon Krijthe

2
如果您有一个可以工作的最近编译的exe文件,您可以使用资源编辑器(如PE Explorer)获取dfm定义。然后,您可以将来自exe的dfm与您现在拥有的dfm进行比较。
我相信也有工具可以将二进制dfm文件转换为文本文件。这将使您更好地查看文件,并帮助您决定它是否真的已损坏。我看到Felix在这个主题上有一些东西。
如果Delphi IDE正常显示表单而没有错误,我不相信会有损坏错误。可能存在包问题吗?您使用运行时包吗?
更新:
您尝试过Eurekalog或madExcept或类似的东西来获取带有调用堆栈和内存转储的更详细的错误消息吗?也许那会给您一些关于问题的线索。
但是通常我认为这个错误是由于缺少运行时包或在uses子句中缺少一个单元。如果您认为您知道哪个组件引起了错误,请搜索源代码中调用RegisterClass()的地方,并查看该单元是否包含在项目的uses子句中。如果没有,请添加它并重试。

2

嗯,dfm文件可以是二进制或文本格式(从4.0版本开始)。

您可以通过右键单击表单并检查Text DFM标志来检查此内容。

如果dfm文件损坏,您可以尝试通过删除所有可疑行来修复它。确保保留object..end集,并且您可能只会失去一些属性值。

顺便说一下,dfm文件应该像这样看起来(以了解一般结构):

object Form5: TForm5
  Left = 0
  DesignSize = (
    426
    652)
  object Button1: TButton
    Left = 343
  end
  object Memo2: TMemo
    Anchors = [akLeft, akTop, akRight, akBottom]
  end
end

如果看起来不是这样,那么你可能正在编辑二进制文件。

1

这可能是因为您更改了自定义组件并从中删除了某个属性。该属性仍在 DFM 中,Delphi 尝试对其进行初始化。

尝试手动从您的 DFM 中删除部分,以便您可以确定哪个组件导致了问题。


1

尝试这个:

  1. 首先备份
  2. 在设计器中右键单击表单;取消选中“文本 DFM”
  3. 保存
  4. 在设计器中右键单击表单;选中“文本 DFM”
  5. 保存

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接