【问题标题】:COM Object - Closed DatasetCOM 对象 - 封闭数据集
【发布时间】:2019-02-25 16:40:45
【问题描述】:

我正在开发一个 Delphi 项目。它是一个调用计算引擎(在 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。它解决了我的问题。

再次感谢您的帮助!

【问题讨论】:

  • COM 对象通常托管在您的本地计算机上。如果是,您应该能够在 IDE 中发现错误(请参阅我尝试的答案);如果不是,您是否尝试过使用远程调试器?顺便说一句,哪个操作系统和 Delphi 版本?
  • 很高兴您找到了解决方案。现在您知道了,可能值得花一点时间在调试器上,看看您是否最终能找到它。
  • 是的,好主意,我一定会这样做的!

标签: oracle delphi debugging com dataset


【解决方案1】:

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

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

您应该能够在 IDE 中进行调试:

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

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

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

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

【讨论】:

  • 嗨MartynA,非常感谢您的评论!我编辑了我的信息来回答你的问题,并发布我得到的感谢你的建议。你觉得你能帮我更多吗? :)
猜你喜欢
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-30
  • 2022-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多