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 requiresCoInitializeEx
to be called because COM based MSXML is used there; - Manually call
CoInitializeEx(nil, COINIT_MULTITHREADED)
when the thread starts and callCoUninitialize()
when it is about to end; - Remove all references to
uROComInit
from theuses
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;