понедельник, 27 октября 2008 г.

Про создание COM-объектов без регистрации DLL в системе

Как известно, чтобы создать некий COM-объект, надо прежде всего зарегистрировать DLL в которой этот объект реализован. И делается это примерно так

regsvr32.exe SomeCOMObjects.dll

Дальше можно вызывать CoCreateInstance, получать экземпляр объекта и работать с ним.

Однако, иногда возникает желание, пользовать объекты не регистрируя библиотеку, например, когда хочется получить portable версию программы. Один способ я описывал вот здесь. Но к сожалению на Vista этот вариант у меня не прошел или я просто не слишком активно пытался.

Второй вариант создавать объект, загружая соответствующую длл-ку при помощи функции LoadLibrary. Выглядит это следующим образом:

показать код

class CCOMDll
{
typedef HRESULT (__stdcall *DllGetClassObjectProc)(REFCLSID rclsid, REFIID riid, LPVOID * ppvObj);
public :
CCOMDll()
: m_sDLLFilePath(_T(""))
, m_hLib(NULL)
, m_pDllGetClassObjectProc(NULL)
, m_pDllCanUnloadNowProc(NULL)
{
}
virtual ~CCOMDll()
{
if (NULL!=m_hLib)
::FreeLibrary(m_hLib);
}
BOOL LoadLibrary(const CString &sDLLFilePath)
{
m_sDLLFilePath = sDLLFilePath;
m_hLib = ::LoadLibrary(m_sDLLFilePath);

m_pDllGetClassObjectProc = (DllGetClassObjectProc)::GetProcAddress(m_hLib, "DllGetClassObject");
return (NULL!=m_hLib);
}
BOOL IsValid() const
{
return (NULL!=m_hLib);
}
//
HRESULT CoCreateInstance(REFCLSID rclsid, REFIID riid, LPVOID* ppvObj)
{
*ppvObj = NULL;
if (NULL==m_pDllGetClassObjectProc)
return S_FALSE;

IClassFactory *pFactory = NULL;
HRESULT hr = (m_pDllGetClassObjectProc)(rclsid, IID_IClassFactory, (void**)&pFactory);
if (S_OK!=hr)
return hr;

hr = pFactory->CreateInstance(NULL, riid, ppvObj);
if (NULL!=pFactory)
pFactory->Release();
return hr;
}
protected :
CString m_sDLLFilePath;
HINSTANCE m_hLib;

DllGetClassObjectProc m_pDllGetClassObjectProc;
};



Понятно, что если делать все по уму надо кой-какую дополнительную обвязку дописать, и выгружать длл-ку тоже следует с осторожностью. Так же не шибко хорошо, когда внутри одного объекта используются объекты из другой библиотеки, которая тоже не зарегистрирована. Т.е. вариант не особо практичный, но в принципе, может кому и пригодится.

Комментариев нет: