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.
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.