Search code examples
delphiservicecom

COM-object in service application cannot be accessed


I`m developing a service application with COM-object in it (OPC Data Access 2.05 server). I have this code for registration my object, which is executed after installation:

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;

The service and COM-object are properly register in the system, so i can see my service in SCM and COM-object in OLE/COM object viewer (and also in OPC clients). The COM-object itself looks like this:

type
  TTestOPCServerDA2 = class(TAutoObject, ITestOPCServerDA2, IConnectionPointContainer, IOPCServer, IOPCCommon, IOPCItemProperties, IOPCBrowseServerAddressSpace)

with its factory registration code:

initialization
  TAutoObjectFactory.Create(ComServer, TTestOPCServerDA2, Class_TestOPCServerDA2, ciMultiInstance, tmApartment);

The problem is when i try to CoCreateInstance(CLASS_TestOPCServerDA2) (via CreateComObject wrapper), i got freeze for 120 second and 0x80080005 (CO_E_SERVER_EXEC_FAILURE) error after. In SCM and Task Manager i see my service is started when COM-object is requested, but nothing else happens. If i stop the serivce and try againg, service would be started again, so i assume Windows knows about my COM-object, its executable and the fact that executable is a service. I also tried to change user which my service is running under (to the same with the invoking application), but that did not help. What am i missing?

Edit 1. I created new project and got rid of OPC (just left COM support) to isolate the problem, so now my class is looks like this:

type
  TTestCOMServer = class(TAutoObject, ITestCOMServer)
  end;
...
initialization
  TAutoObjectFactory.Create(ComServer, TTestCOMServer, Class_TestCOMServer, ciMultiInstance, tmApartment);

And the service thread:

procedure TCOMService.ServiceExecute(Sender: TService);
begin
  while (not Terminated) do
  begin
    ReportStatus;
    ServiceThread.ProcessRequests(False);

    Sleep(25);
  end;

The problem persists: when i try to CoCreateInstance, nothing happens and calling app hangs for 120 seconds. But! If i make 1 change: uncommenting Application.DelayInitialize := True; in dpr, COM-object gets created well and calling app freezes no longer! Is it the service execute thread that (not service main thread) processes COM-requests?

Edit 2. It seems that only DelayInititalization is requred. ProcessRequests can be called with False argument and sleep can have its place - i must have not properly rebuilded my project. So, i think the answer to my question is to uncomment Application.DelayInitialize := True; in DPR-file. Delphi autogenerate text about that, but it mentions only Windows 2003 Server condition and my OS is Windows 10.


Solution

  • In my case (Delphi XE3 under Windows 10 Pro) i had to uncomment

    Application.DelayInitialize := True;
    

    in DPR. After this change, COM-object is created properly.