oracle - 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。它解决了我的问题。
再次感谢你的帮助!
解决方案
我不打算推测可能导致您的应用程序行为发生变化的原因:如果您需要这方面的帮助,则需要提供MCVE。当然,问题是,如果您可以提供 MCVE,那么您将有足够的知识来识别和解决问题。
但我认为您应该能够通过从 Delphi IDE 中调试 .DLL 以一种非常简单的方式自己定位和修复错误:
您应该能够从 IDE 中调试它:
将生成 .Dll 的项目加载到 IDE 中,对其进行编译并在它创建 COM 对象的位置放置一个断点。
然后,启动调用 COM 对象的任何进程,并且断点应该触发,因此您可以从那里创建执行。
你试过吗?可能这就是您在 q 中要说的内容,只是您说“然后我从代码中启动引擎(在 IDE 中按 Start),然后启动调用引擎的应用程序。” 如果 COM 对象托管在 DLL 中,这听起来不正确。
如果 COM 对象的创建导致异常,调试器应捕获该异常,以便您可以从调用堆栈(使用查看 | 调试窗口 | 调用堆栈)中查看异常发生的确切位置。通常,只需查看调用堆栈就足以确定原因所在。
推荐阅读
- pentaho - 为什么我在 pentaho cde 中传递日期参数时看不到示例数据图表?
- reactjs - reactjs链接不起作用,在ajax请求后渲染时
- netsuite - 通过 Suitelet 使用 Netsuite 信用卡付款
- primefaces - 在 Primefaces 数据表单元格编辑器中选择每个项目上的选择行复选框
- python - 为衰减变量优化以下python代码部分
- git - 如何在 azure devops 中设置默认分支策略
- c - 试图从 C 代码中获取 windows 版本
- mongodb - MongoDB克隆到另一个集群
- reactjs - 如何在material-ui中同时激活所有步骤?
- c# - How to make EF Core tools obtain DbContext instance from service provider of a console application?