【发布时间】:2021-08-24 13:41:00
【问题描述】:
我正在开发一个包含 COM 对象的服务应用程序(OPC 数据访问 2.05 服务器)。我有这个代码来注册我的对象,安装后执行:
procedure TOPCService.ServiceAfterInstall(Sender: TService);
var
lcHResult: HRESULT;
lcCLSIDString: String;
begin
ComServer.UpdateRegistry(True);
lcCLSIDString:=GUIDToString(CLASS_TestOPCServerDA2);
ComObj.CreateRegKey('AppID\'+lcCLSIDString, '', 'Test OPC Server DA2');
ComObj.CreateRegKey('AppID\'+Application.ExeName, 'AppId', lcCLSIDString);
ComObj.CreateRegKey('CLSID\'+lcCLSIDString+'\VersionIndependentProgID', '', C_TEST_OPC_DA2_SERVER_NAME);
<opc server registration stuff>
RegisterAsService(lcCLSIDString, Name);
end;
服务和 COM 对象已在系统中正确注册,因此我可以在 SCM 中看到我的服务,并在 OLE/COM 对象查看器(以及 OPC 客户端)中看到我的服务。 COM 对象本身如下所示:
type
TTestOPCServerDA2 = class(TAutoObject, ITestOPCServerDA2, IConnectionPointContainer, IOPCServer, IOPCCommon, IOPCItemProperties, IOPCBrowseServerAddressSpace)
带有工厂注册码:
initialization
TAutoObjectFactory.Create(ComServer, TTestOPCServerDA2, Class_TestOPCServerDA2, ciMultiInstance, tmApartment);
问题是当我尝试 CoCreateInstance(CLASS_TestOPCServerDA2)(通过 CreateComObject 包装器)时,我冻结了 120 秒,之后出现 0x80080005 (CO_E_SERVER_EXEC_FAILURE) 错误。在 SCM 和任务管理器中,我看到我的服务在请求 COM 对象时启动,但没有其他任何反应。如果我停止服务并再次尝试,服务将再次启动,所以我假设 Windows 知道我的 COM 对象、它的可执行文件以及可执行文件是服务的事实。 我还尝试更改运行我的服务的用户(与调用应用程序相同),但这没有帮助。 我错过了什么?
编辑 1. 我创建了新项目并摆脱了 OPC(刚刚离开 COM 支持)以隔离问题,所以现在我的课程如下所示:
type
TTestCOMServer = class(TAutoObject, ITestCOMServer)
end;
...
initialization
TAutoObjectFactory.Create(ComServer, TTestCOMServer, Class_TestCOMServer, ciMultiInstance, tmApartment);
还有服务线程:
procedure TCOMService.ServiceExecute(Sender: TService);
begin
while (not Terminated) do
begin
ReportStatus;
ServiceThread.ProcessRequests(False);
Sleep(25);
end;
问题仍然存在:当我尝试 CoCreateInstance 时,没有任何反应,调用应用程序挂起 120 秒。 但是!如果我进行 1 处更改:取消注释 Application.DelayInitialize := True; 在 dpr 中,COM 对象会被很好地创建并且调用应用程序不再冻结!是服务执行线程(不是服务主线程)处理 COM 请求吗?
编辑 2. 似乎只需要延迟初始化。 ProcessRequests 可以使用 False 参数调用,并且 sleep 可以占有一席之地 - 我一定没有正确重建我的项目。 所以,我认为我的问题的答案是取消注释 Application.DelayInitialize := True; 在 DPR 文件中。 Delphi 会自动生成有关该内容的文本,但它仅提及 Windows 2003 Server 条件,而我的操作系统是 Windows 10。
【问题讨论】:
-
CO_E_SERVER_EXEC_FAILURE 表示“服务器执行失败”,表示您的COM服务器未能及时注册对象或未能响应调用的接口等。可能有很多原因。如果没有完整的重现代码,很难说更多。
-
您是否尝试过使用常规可执行文件(不是服务)?
-
是的,一切都像常规应用程序一样正常。我用新信息编辑了我的帖子。