首页 > 解决方案 > COM 对象 - 封闭数据集

问题描述

我正在做一个德尔福项目。它是一个调用计算引擎(在 Delphi 中)的应用程序,该引擎从 Oracle 数据库中检索数据。该项目有效,但我在调试时遇到了麻烦。

为了调试引擎,我用计算引擎的 dll 创建了一个 COM 对象;我让应用程序调用本地主机(即在我的 COM 对象中运行的引擎)。然后我从代码中启动引擎(在 IDE 中按 Start),并启动调用引擎的应用程序。它通常像一个魅力一样工作——代码在我在引擎代码中设置的断点处停止。

但是几天以来,每次我尝试这样做时,都会收到一条由 Dataset.State=dsInactive 事实生成的错误消息。不过,我没有更改代码中的任何内容;在数据库和我的计算机之间打开了流程(我 ping 和 telnet 都可以)。

你知道什么会导致这个问题吗?

非常感谢您的帮助!

编辑 1: 非常感谢 MartynA 的回答!

您所描述的确实是我想说的-至少在开始时:我确实将生成.dll的项目加载到IDE中,对其进行编译并放置断点,但是我的断点是错误消息出现的位置:

     procedure TRNParameters.SetDataset(ADataset: TClientDataSet);

begin
      if ADataset = nil then
        TRNException.RaiseTechnicalException('Erreur à la création de l''objet TRNParameters : le dataset des paramètres est nil');

      if ADataset.State = dsInactive then
        TRNException.RaiseTechnicalException('Erreur à la création de l''objet TRNParameters : le dataset des paramètres est fermé');

我收到的消息是第二条消息,并且确实到达了该行上的断点 - 代码进入那个“如果” - 在显示消息之前的那一刻。

我检查了调用堆栈,我得到:

URNParams.TRNParameters.SetDataset($31345F0)
URNParams.TRNParameters.Create(???,nil)
SCEPlgFRObjectImpl.TSCEPlgFRObject.MtsDataModuleCreate(???)
:02ce0a2a TDataModule.DoCreate + $2E
:02ce086c TDataModule.Create + $E0
:02d31b70 TRemoteDataModule.Create + $38
:02d792af TComponentFactory.CreateComObject + $F
:02ccda34 TComObjectFactory.CreateInstance + $1C
:02d79211 TComponentFactory.CreateInstance + $C5
:75c58bc6 ; C:\windows\syswow64\ole32.dll
:75c73060 ; C:\windows\syswow64\ole32.dll
:7662a419 ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:7662ad82 ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:7662adf9 ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:7662ae0f ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:7662aea1 ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:7662af94 ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:765d93ca ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:765d93aa ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:7666b7ee ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:7666b9d2 ; C:\WINDOWS\SysWOW64\COMSVCS.DLL
:76271287 msvcrt._itow_s + 0x4c
:76271328 msvcrt._endthreadex + 0x6c
:7594343d kernel32.BaseThreadInitThunk + 0x12
:778e9802 ntdll.RtlInitializeExceptionChain + 0x63
:778e97d5 ntdll.RtlInitializeExceptionChain + 0x36

所以我猜这个问题来自于 SCEPlgFRObjectImpl.TSCEPlgFRObject.MtsDataModuleCreate(???) 这一行。所以我在 MtsDataModuleCreate 中设置了一个断点,最终得到了更准确的错误信息:

    try
    OraSessionFRA_SPU.Open;
  except
    on e: Exception do
    begin
      WriteLog('SCEPlgFR - ConnectDatabase : ConnectString=' + OraSessionFR_SPU.ConnectString);
      WriteLog('SCEPlgFR - ConnectDatabase : ' + e.Message);
      raise Exception.Create('SCEPlgFR - ConnectDatabase : ' + #13#10 + e.Message);
    end;
  end;

但!消息无法访问(由于优化)!你知道我怎么能读到那条消息吗?

另外,我不知道如何找到 COM 对象的创建位置,它是应该在我的 Delphi 代码中的一段代码吗?(对不起,我对 Delphi 和 COM 对象很陌生!)

非常感谢你的帮助!

编辑 2

大家好,我创建了一个字符串变量 Mess 并添加了一个Mess:=e.Message来捕获错误消息。我得到一个“ORA-12154:TNS:无法解析指定的连接标识符”。

我想我能从中找到出路。非常感谢MartynA,你是我的超级英雄!

编辑 3 大家好,这是问题的解决方案:我的 Delphi 找不到具有所需连接的 TNS。(可能是因为我必须进行冲突安装来开发与不同 Oracle 飞行员一起工作的不同软件)。所以数据集无法打开的原因是因为无法连接到数据库(因为无法访问正确的 TNS)。一位同事让我创建了一个 TNS_ADMIN 环境变量,该变量的路径指向所需的 TNS。它解决了我的问题。

再次感谢你的帮助!

标签: oracledelphidebuggingcomdataset

解决方案


我不打算推​​测可能导致您的应用程序行为发生变化的原因:如果您需要这方面的帮助,则需要提供MCVE。当然,问题是,如果您可以提供 MCVE,那么您将有足够的知识来识别和解决问题。

但我认为您应该能够通过从 Delphi IDE 中调试 .DLL 以一种非常简单的方式自己定位和修复错误:

您应该能够从 IDE 中调试它:

  • 将生成 .Dll 的项目加载到 IDE 中,对其进行编译并在它创建 COM 对象的位置放置一个断点。

  • 然后,启动调用 COM 对象的任何进程,并且断点应该触发,因此您可以从那里创建执行。

你试过吗?可能这就是您在 q 中要说的内容,只是您说“然后我从代码中启动引擎(在 IDE 中按 Start),然后启动调用引擎的应用程序。” 如果 COM 对象托管在 DLL 中,这听起来不正确。

如果 COM 对象的创建导致异常,调试器应捕获该异常,以便您可以从调用堆栈(使用查看 | 调试窗口 | 调用堆栈)中查看异常发生的确切位置。通常,只需查看调用堆栈就足以确定原因所在。


推荐阅读