-
Необходимо зарегистрировать TypeLib моего COM сервера только на время выполнения программы. При этом программа выполняется без прав администратора. Сам КОМ сервер регистрируется нормально (без внесения себя в реестр), а TypeLib при регистрации (RegisterTypeLib) требует прав администратора для того чтобы занестись в реестр. Можно ли ее зарегистрировать на время выполнения программы без внесения в реестр?
-
> Сам КОМ сервер регистрируется нормально (без внесения себя > в реестр)
Это как ?
-
> Это как ?
Приложение запускается и выполняет CoRegisterClassObject, после чего данный класс доступен в системе, пока приложение выполняется.
-
Понятно. А typelib твоему COM-контроллеру зачем понадобилась ? xxx_tlb.pas разве недостаточно ?
-
> Сергей М. © (26.03.09 11:29) [3]
Ком-сервер и Ком-клиент - это разные процессы и без typelib взаимодействие не работает. И логично предположить, что КОМ не знает сколько и какие параметры я описал в методах интерфейса, и не может передавать их между процессами.
-
> Дмитрий С (26.03.09 11:42) [4]
Твой COM-сервер есть наследник TTypedComObject ?
-
Нет.
TDataConnection = class(TObject, IDataConnection, IClassFactory, IUnknown)
У меня объект в единственном экземпляре существует, и поэтому я решил его и собственной фабрикой сделать.
-
см. справку по TTypedComObject
IProvideClassInfo has a single method, GetClassInfo, which is implemented in TTypedComObject to provide access to the type information for the object’s CoClass entry in its type library. This means that if the TTypedComObject has a running instance, a client can query for the IProvideClassInfo interface and retrieve this information without having to load and navigate a type library to find the ITypeInfo pointer for the object’s CoClass
Это означает, что твой СОМ-сервер должен реализовать как минимум интерфейс IProvideClassInfo
-
Реализовал и IProvideClassInfo и IProvideClassInfo2 - никакого эффекта. СОМ даже не вызывает методы этих интерфейсов.
-
Покажи код своего COM-контроллера..
-
unit uDataComSrv;
interface
uses
Launcher_TLB, Windows, ActiveX, StdVcl;
type
TDataConnection = class(TObject, IDataConnection, IClassFactory, IUnknown)
private
class var FDataConnection: TDataConnection;
class var FRegId: Integer;
class var FTypeLib: ITypeLib;
class procedure Initialize;
class procedure Finalize;
public
function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
function CreateInstance(const unkOuter: IUnknown; const iid: TIID;
out obj): HResult; stdcall;
function LockServer(fLock: BOOL): HResult; stdcall;
procedure Test(const Str: WideString); safecall;
end;
implementation
uses ComObj, SysUtils;
function TDataConnection.CreateInstance(const unkOuter: IInterface;
const iid: TIID; out obj): HResult;
begin
Result := QueryInterface(iid, obj);
end;
class procedure TDataConnection.Finalize;
begin
OleCheck(CoRevokeClassObject(FRegID));
FDataConnection.Free;
end;
class procedure TDataConnection.Initialize;
begin
FDataConnection := TDataConnection.Create;
OleCheck(LoadTypeLibEx(PWideChar(WideString(ParamStr(0))), REGKIND_DEFAULT, FTypeLib));
OleCheck(RegisterTypeLib(FTypeLib, PWideChar(WideString(ParamStr(0))), nil));
OleCheck(CoRegisterClassObject(
CLASS_DataConnection,
FDataConnection,
CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE,
FRegID
));
end;
function TDataConnection.LockServer(fLock: BOOL): HResult;
begin
Result := E_NOTIMPL;
end;
function TDataConnection.QueryInterface(const IID: TGUID; out Obj): HRESULT;
begin
if GetInterface(IID, Obj) then
Result := S_OK
else
Result := E_NOINTERFACE;
end;
procedure TDataConnection.Test;
begin
MessageBoxW(GetActiveWindow, PWideChar(Str), nil, 0);
end;
function TDataConnection._AddRef: Integer;
begin
Result := 1;
end;
function TDataConnection._Release: Integer;
begin
Result := 1;
end;
initialization
CoInitialize(nil);
TDataConnection.Initialize;
finalization
TDataConnection.Finalize;
CoUninitialize;
end. Реализацию IProvideClassInfo я пока стер. Могу восстановить.
-
> Дмитрий С (27.03.09 04:48) [10]
Я код контроллера спросил, а не сервера.. Разницу понимаешь ?
-
> Сергей М. © (27.03.09 08:28) [11]
Стесняюсь спросить, что это? Этот модуль это все, что у меня пока есть + еще TypeLib.
-
"Клиент" это по-вашему по-неправильному..
-
Ясно. Спасибо, буду знать. var
DC: IDataConnection;
...
OleCheck(CoCreateInstance(
CLASS_DataConnection,
nil,
CLSCTX_LOCAL_SERVER,
IID_IDataConnection,
DC
));
Dc.Test('Test text');
-
Так. И ты хочешь сказать, что при наличии в проекте контроллера соответствующего xxx_tlb.pas строка с вызовом метода Test вызывает проблемы, если библ-ка типов не зарегистрирована в реестре ?
-
Так и есть. xxx_tlb.pas один и тот же у них.
Даже в рамках одного процесса вызов OleCheck(CoCreateInstance( ... ));
Выдает ошибку Интерфейс не зарегистрирован.
-
А что собссно мешает сделать класс COM-сервера наследником TAutoObject ? IDispath ведь зарегистрирован в реесте ..
-
Ничего не мешает. Наверное будет даже лучше на этапе разработки не иметь "строгих" интерфейсов.
Но все же, не регистрируя TypeLib и интерфейс соответственно нельзя его использовать СОМом?
-
Подозреваю что можно. Но подробностями не владею. Обратись к Григорьеву Антону (С) - он большой дока в СОМ-технологии
-
Я думаю, что все-же нельзя. Небольшое углубление показывает, что в новых версиях окон есть функция RegisterTypeLibForUser, которая эту роль и выполняет.
RegisterTypeLibForUser has functionality identical to RegisterTypeLib except that type library is registered for use only by the calling user identity.
Requirements: Windows NT/2000: Requires Windows Server 2003 or later. Windows 95/98: Not supported.
Поэтому остановлюсь пока на IDispath
-
Без регистрации обойтись можно, но очень хлополтно. Если сервер и клиент выполняются в разных адресных пространствах, то кто-то должен построить для них заместителя и заглушку. Сервер, в принципе, сам может построить заглушку в своём адресном пространстве, но клиенту по-любому её должна загрузить система из внешней библиотеки. Система запрашивает у COM-объекта интерфейс IMarshal, и если объект его реализует, то с его помощью может сам построить заглушку, а также указать системе, какую библиотеку загрузить в адресное пространство клиента, чтобы она построила там заглушку (эту библиотеку тоже должны будете написать вы сам). Но если IMarshal, как это обычно бывает, не реализован, то система проверяет, как интерфейс зарегистрирован в реестре, и ищет соответствующую proxy/stub dll (в случае стандартного маршалинга) или библиотеку типов (в случае универсального маршалинга). И тут, видимо, ничего не сделаешь, они обязаны быть зарегистрированными в реестре, чтобы система их нашла. Если вас заинтересовал IMarshal, об этом можно почитать здесь: http://www.rsdn.ru/article/com/marsh.xml#EGFAEНо если ограничения на типы и производительность, которые даёт IDispatch, вас устраивают, намного проще будет использовать его.
|