Конференция "Corba" » Как временно зарегистрировать TypeLib? [Delphi, Windows]
 
  • Дмитрий С (26.03.09 05:04) [0]
    Необходимо зарегистрировать TypeLib моего COM сервера только на время выполнения программы. При этом программа выполняется без прав администратора.
    Сам КОМ сервер регистрируется нормально (без внесения себя в реестр), а TypeLib при регистрации (RegisterTypeLib) требует прав администратора для того чтобы занестись в реестр.
    Можно ли ее зарегистрировать на время выполнения программы без внесения в реестр?
  • Сергей М. © (26.03.09 10:09) [1]

    > Сам КОМ сервер регистрируется нормально (без внесения себя
    > в реестр)


    Это как ?
  • Дмитрий С (26.03.09 10:34) [2]

    > Это как ?

    Приложение запускается и выполняет CoRegisterClassObject, после чего данный класс доступен в системе, пока приложение выполняется.
  • Сергей М. © (26.03.09 11:29) [3]
    Понятно.
    А typelib твоему COM-контроллеру зачем понадобилась ?
    xxx_tlb.pas разве недостаточно ?
  • Дмитрий С (26.03.09 11:42) [4]

    > Сергей М. ©   (26.03.09 11:29) [3]

    Ком-сервер и Ком-клиент - это разные процессы и без typelib взаимодействие не работает.
    И логично предположить, что КОМ не знает сколько и какие параметры я описал в методах интерфейса, и не может передавать их между процессами.
  • Сергей М. © (26.03.09 11:58) [5]

    > Дмитрий С   (26.03.09 11:42) [4]


    Твой COM-сервер есть наследник TTypedComObject ?
  • Дмитрий С (26.03.09 12:24) [6]
    Нет.

    TDataConnection = class(TObject, IDataConnection, IClassFactory, IUnknown)

    У меня объект в единственном экземпляре существует, и поэтому я решил его и собственной фабрикой сделать.
  • Сергей М. © (26.03.09 12:53) [7]
    см. справку по 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
  • Дмитрий С (26.03.09 13:05) [8]
    Реализовал и IProvideClassInfo и IProvideClassInfo2 - никакого эффекта. СОМ даже не вызывает методы этих интерфейсов.
  • Сергей М. © (26.03.09 16:18) [9]
    Покажи код своего COM-контроллера..
  • Дмитрий С (27.03.09 04:48) [10]
    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;

       // ClassFactory
       function CreateInstance(const unkOuter: IUnknown; const iid: TIID;
         out obj): HResult; stdcall;
       function LockServer(fLock: BOOL): HResult; stdcall;

       // DataConnection
       procedure Test(const Str: WideString); safecall;

     end;
    implementation

    uses ComObj, SysUtils;

    { TDataConnection }

    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 08:28) [11]

    > Дмитрий С   (27.03.09 04:48) [10]


    Я код контроллера спросил, а не сервера..
    Разницу понимаешь ?
  • Дмитрий С (27.03.09 08:34) [12]

    > Сергей М. ©   (27.03.09 08:28) [11]

    Стесняюсь спросить, что это? Этот модуль это все, что у меня пока есть + еще TypeLib.
  • Сергей М. © (27.03.09 08:54) [13]
    "Клиент" это по-вашему по-неправильному..
  • Дмитрий С (27.03.09 09:21) [14]
    Ясно. Спасибо, буду знать.

    var
     DC: IDataConnection;
    ...
     OleCheck(CoCreateInstance(
       CLASS_DataConnection,
       nil,
       CLSCTX_LOCAL_SERVER,
       IID_IDataConnection,
       DC
     ));

     Dc.Test('Test text');

  • Сергей М. © (27.03.09 09:30) [15]
    Так.
    И ты хочешь сказать, что при наличии в проекте контроллера соответствующего xxx_tlb.pas строка с вызовом метода Test вызывает проблемы, если библ-ка типов не зарегистрирована в реестре ?
  • Дмитрий С (27.03.09 09:39) [16]
    Так и есть. xxx_tlb.pas один и тот же у них.

    Даже в рамках одного процесса  вызов
    OleCheck(CoCreateInstance(   ... ));

    Выдает ошибку Интерфейс не зарегистрирован.
  • Сергей М. © (27.03.09 10:04) [17]
    А что собссно мешает сделать класс COM-сервера наследником TAutoObject ?
    IDispath ведь зарегистрирован в реесте ..
  • Дмитрий С (27.03.09 10:30) [18]
    Ничего не мешает. Наверное будет даже лучше на этапе разработки не иметь "строгих" интерфейсов.

    Но все же, не регистрируя TypeLib и интерфейс соответственно нельзя его использовать СОМом?
  • Сергей М. © (27.03.09 10:47) [19]
    Подозреваю что можно. Но подробностями не владею.
    Обратись к Григорьеву Антону (С) - он большой дока в СОМ-технологии
  • Дмитрий С (27.03.09 11:37) [20]
    Я думаю, что все-же нельзя. Небольшое углубление показывает, что в новых версиях окон есть функция 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
  • Григорьев Антон © (28.03.09 09:16) [21]
    Без регистрации обойтись можно, но очень хлополтно. Если сервер и клиент выполняются в разных адресных пространствах, то кто-то должен построить для них заместителя и заглушку. Сервер, в принципе, сам может построить заглушку в своём адресном пространстве, но клиенту по-любому её должна загрузить система из внешней библиотеки. Система запрашивает у COM-объекта интерфейс IMarshal, и если объект его реализует, то с его помощью может сам построить заглушку, а также указать системе, какую библиотеку загрузить в адресное пространство клиента, чтобы она построила там заглушку (эту библиотеку тоже должны будете написать вы сам). Но если IMarshal, как это обычно бывает, не реализован, то система проверяет, как интерфейс зарегистрирован в реестре, и ищет соответствующую proxy/stub dll (в случае стандартного маршалинга) или библиотеку типов (в случае универсального маршалинга). И тут, видимо, ничего не сделаешь, они обязаны быть зарегистрированными в реестре, чтобы система их нашла.

    Если вас заинтересовал IMarshal, об этом можно почитать здесь: http://www.rsdn.ru/article/com/marsh.xml#EGFAE
    Но если ограничения на типы и производительность, которые даёт IDispatch, вас устраивают, намного проще будет использовать его.
 
Конференция "Corba" » Как временно зарегистрировать TypeLib? [Delphi, Windows]
Есть новые Нет новых   [119261   +45][b:0][p:0.002]