Можно ли каким-нибудь образом получить незарегистрированный с системном реестре объект и соответсnвенно его дисп-интерфейсы? Аналогия — получение незарегистрированного ITypeLib. Т.е. есть ДЛЛ с прикомпонованной библиотекой типа и кучей объектов и интерфейсов, и есть желание работаь с ней не без регистрации (regsvr32.exe). Поможите, люди добрые, а то ведь могу и сам разобраться.
Здравствуйте Raul, Вы писали:
R>Можно ли каким-нибудь образом получить незарегистрированный с системном реестре объект и соответсnвенно его дисп-интерфейсы? Аналогия — получение незарегистрированного ITypeLib. Т.е. есть ДЛЛ с прикомпонованной библиотекой типа и кучей объектов и интерфейсов, и есть желание работаь с ней не без регистрации (regsvr32.exe). Поможите, люди добрые, а то ведь могу и сам разобраться.
А в чём проблема?
В каждой DLL есть 4 дополнительных, связанных с СОМ входа. Один из них — DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv). Передаёшь туда CLSID кокласса и IID_IClassFactory, получаешь класс-фактори, у неё просишь CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) с IID_IDispatch. Маршаллинга тебе не треба, раз DLL. Что ещё нужно, чтобы "встретить достойную старость"?
Здравствуйте Vi2, Вы писали:
Vi2>А в чём проблема? Vi2>В каждой DLL есть 4 дополнительных, связанных с СОМ входа. Один из них — DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv). Передаёшь туда CLSID кокласса и IID_IClassFactory, получаешь класс-фактори, у неё просишь CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) с IID_IDispatch. Маршаллинга тебе не треба, раз DLL. Что ещё нужно, чтобы "встретить достойную старость"?
Возможно,я не совсем корректно описал заморочку.
А проблема вот в чем. Метод с DllGetClassObject работает, если сия библиотека уже зарегистрирована. А иначе — следующий кусок кода
HRESULT hr;
HINSTANCE hDll=::LoadLibrary("ordam20.dll");
DWORD dw=GetLastError();
HRESULT (STDAPICALLTYPE *pfnGetCo)(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
(FARPROC&) pfnGetCo=::GetProcAddress(hDll,"DllGetClassObject");
IClassFactory *piCf=NULL;
hr=pfnGetCo(CLSID_ORAsyncConnection,IID_IClassFactory,(void**)&piCf);
LPDISPATCH lpDisp=NULL;
hr=piCf->CreateInstance(NULL,IID_IORAsyncConnection,(void**)&lpDisp);
/* class Client_IORAsyncConnection : public COleDispatchDriver
{
...
long GetTimeout();
...
};*/
Client_IORAsyncConnection iAConn(lpDisp);
long l=iAConn.GetTimeout(); // throw COleException {m_sc=0x8002801D(библиотека не зарегистрирована)}
сваливается в COleException с SCODE 0x8002801D(библиотека не зарегистрирована). Возможно, это связано с реализацией собственно сервера — он регистрирует, помимо компонента с CLSID_ORAsyncConnection, еще пару СО и библиотеку типов; хотя я не уверен в том, что он использует эти объекты СОМ. К сожалению, реализация сервера не доступна, также, как и его разработчики. Вопрос — Есть ли еще какие-либо методы работы с незарегистрированными объектами СОМ.
Здравствуйте Аноним, Вы писали:
А>сваливается в COleException с SCODE 0x8002801D(библиотека не зарегистрирована). Возможно, это связано с реализацией собственно сервера — он регистрирует, помимо компонента с CLSID_ORAsyncConnection, еще пару СО и библиотеку типов; хотя я не уверен в том, что он использует эти объекты СОМ. К сожалению, реализация сервера не доступна, также, как и его разработчики. Вопрос — Есть ли еще какие-либо методы работы с незарегистрированными объектами СОМ.
Скорее всего это связано с работой Invoke в объекте — он работает через ITypeInfo. Чтобы убедиться в этом, убери регистрацию этой DLL и сделай простую регистрацию TLB из DLL через REGTLIB.exe в ком.строке или RegisterTypeLib() в программе. Она зарегистрирует только TLB без коклассов. Если это не поможет, значит, она внутри создаёт коклассы. Тогда — увы — ничего сделать нельзя.
Здравствуйте Vi2, Вы писали:
Vi2>Скорее всего это связано с работой Invoke в объекте — он работает через ITypeInfo. Чтобы убедиться в этом, убери регистрацию этой DLL и сделай простую регистрацию TLB из DLL через REGTLIB.exe в ком.строке или RegisterTypeLib() в программе. Она зарегистрирует только TLB без коклассов. Если это не поможет, значит, она внутри создаёт коклассы. Тогда — увы — ничего сделать нельзя.
Хотя, ты же сам можешь вызвать в начале DllRegisterServer и в конце DllUnregisterServer, оставляя Реестре нетронутым.
Здравствуйте Vi2, Вы писали:
Vi2>>Скорее всего это связано с работой Invoke в объекте — он работает через ITypeInfo. Чтобы убедиться в этом, убери регистрацию этой DLL и сделай простую регистрацию TLB из DLL через REGTLIB.exe в ком.строке или RegisterTypeLib() в программе. Она зарегистрирует только TLB без коклассов. Если это не поможет, значит, она внутри создаёт коклассы. Тогда — увы — ничего сделать нельзя.
Vi2>Хотя, ты же сам можешь вызвать в начале DllRegisterServer и в конце DllUnregisterServer, оставляя Реестре нетронутым.
Действительно, методом научного тыка установлено, что упомянутый код работает, если в реестре есть ветка с описанием typelib данного сервака, все остальное можно удалить. Ну а в общем-то, я уже допер, как все это можно сделать в моем случае. Так что — всем спасибо (особенно Vi2), все свободны.