【问题标题】:COM-object in service application cannot be accessed无法访问服务应用程序中的 COM 对象
【发布时间】: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服务器未能及时注册对象或未能响应调用的接口等。可能有很多原因。如果没有完整的重现代码,很难说更多。
  • 您是否尝试过使用常规可执行文件(不是服务)?
  • 是的,一切都像常规应用程序一样正常。我用新信息编辑了我的帖子。

标签: delphi service com


【解决方案1】:

就我而言(Windows 10 Pro 下的 Delphi XE3)我不得不取消注释

Application.DelayInitialize := True;

在 DPR。在此更改之后,COM 对象被正确创建。

【讨论】:

    猜你喜欢
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    相关资源
    最近更新 更多