COM Frequently Asked Questions


How can I execute Dialogs on Windows?

There are a way to execute dialogs (e.g. with TOpenDialog.Execute()) on Windows after initializing the COM library using CoInitializeEx with the COINIT_MULTITHREADED flag.

CoInitializeEx calls affect only the thread it is being executed on. So, do the following:

  • Move all the stuff requiring CoInitializeEx(nil, COINIT_MULTITHREADED) into a separate thread. Remoting SDK requires CoInitializeEx to be called because COM based MSXML is used there;
  • Manually call CoInitializeEx(nil, COINIT_MULTITHREADED) when the thread starts and call CoUninitialize() when it is about to end;
  • Remove all references to uROComInit from the uses lists.

As an example, consider this fragment of code:

type
TServiceThread = class(TThread)
  fResult1: Integer;
  fResult2: TDateTime;
  fMessage: IROMessage;
  fTransportChannel: IROTransportChannel;
public
  constructor Create(aMessage: IROMessage; aTransportChannel: IROTransportChannel);
  procedure Execute; override;
  procedure GetResult;
end;

constructor TServiceThread.Create(aMessage: IROMessage; aTransportChannel: IROTransportChannel);
begin
  fMessage := aMessage;
  fTransportChannel := aTransportChannel;
  inherited Create(False);
end;

procedure TServiceThread.Execute;
var
  fService: INewService;
begin
  CoInitializeEx(nil,  COINIT_MULTITHREADED);
  fService := CoNewService.Create(fMessage, fTransportChannel);
  fResult1 := fService.Sum(1, 2);
  fResult2 := fService.GetServerTime;
  Synchronize(GetResult);
  CoUninitialize();
end;

procedure TServiceThread.GetResult;
begin
  ClientForm.Label1.Caption := IntToStr(fResult1);
  ClientForm.Label2.Caption := DateTimeToStr(fResult1);
end;

procedure TClientForm.RunService;
var
  fServiceThread: TServiceThread;
begin
  fServiceThread := TServiceThread.Create(ROMessage, ROChannel);
  fServiceThread.WaitFor;
  FreeAndNil(fServiceThread);
end;