Windows/C++: как использовать COM dll, который не регистрируется

В нашем приложении мы должны использовать COM dll (а именно, msdia100.dll), который не был зарегистрирован в системе прежде.

Earler, мы только что назвали DLL путем вызова его DllRegisterServer с помощью этого кода:

// Register DIA DLL required by Breakpad
std::string diaLibPath = "msdia100";    
HMODULE diaLib = LoadLibrary(diaLibPath.c_str());
if( diaLib == NULL )
{
    errors << "Cannot load DLL " << diaLibPath << endl;
    return;
}

typedef HRESULT ( __stdcall * regServer_t )(void);

regServer_t regServer = (regServer_t)GetProcAddress(diaLib, "DllRegisterServer");
if( regServer == NULL )
{
    errors << "Cannot get method DllRegisterServer from " << diaLibPath << endl;
    FreeLibrary(diaLib);
    return;
}
if( regServer() != S_OK )
{
    errors << "Cannot call DllRegisterServer from " << diaLibPath << endl;
}
FreeLibrary(diaLib);

Это больше не работает над Windows 7 (возможно, также Vista, не сделал попробованный), потому что для вызывания этой функции этому нужны Права администратора.

Все решения этой проблемы я нашел где о получении тех прав администратора. Это не возможное решение для нас, потому что наше приложение должно также работать, если пользователь не может получить те права администратора.

Также никакое решение для нас для внезапной необходимости в установщике для нашего приложения не регистрирует этот DLL.

Так, что возможности там? Как я могу использовать этот DLL без прав администратора? Я должен повторно кодировать COM, который работает без потребности зарегистрировать DLL сначала?


Код, где я использую этот lib, похож на это:

CComPtr<IDiaDataSource> data_source;
if (FAILED(data_source.CoCreateInstance(CLSID_DiaSource))) {
  fprintf(stderr, "CoCreateInstance CLSID_DiaSource failed "
          "(msdia80.dll unregistered?)\n");
  return false;
}

(Btw., для тех, кому интересно: Это - часть Google Breakpad.)

5
задан Albert 18 March 2010 в 16:25
поделиться

2 ответа

Думаю, вам стоит попробовать COM без регистрации. См .: http://msdn.microsoft.com/en-us/library/ms973913.aspx

[править] Кроме того, я нашел обратно ссылку на обсуждение, где утверждается, что подойдет только LoadLibrary . Однако на собственном опыте не могу подтвердить, что это работает. См .: http://www.eggheadcafe.com/forumarchives/win32programmerole/Dec2005/post25120399.asp

5
ответ дан 18 December 2019 в 14:44
поделиться

Простой подход - использовать LoadLibrary ("msdia100.dll") для загрузки библиотеки DLL напрямую. Затем используйте GetProcAddress ("DllGetClassObject"). Затем вы можете использовать IClassFactory для выполнения эквивалента CoCreateInstance.

Примерно так. (Заявление об ограничении ответственности: я не скомпилировал это ...)

HRESULT CoCreateDiaDataSource(CComPtr<IDiaDataSource>& data_source)
{
    HMODULE hmodule = LoadLibrary("MSDIA100");
    if (!hmodule)
        return HRESULT_FROM_WIN32(GetLastError()); // library not found

    BOOL (WINAPI*DllGetClassObject)(REFCLSID,REFIID,LPVOID*) =
        (BOOL(WINAPI*)(REFCLSID,REFIID,LPVOID*))GetProcAddress(hmodule, "DllGetClassObject");

    if (!DllGetClassObject) 
        return HRESULT_FROM_WIN32(GetLastError());

    CComPtr<IClassFactory> pClassFactory;
    HRESULT hr = DllGetClassObject(CLSID_DiaSource, IID_IClassFactory, &pClassFactory);
    if (FAILED(hr))
        return hr;

    hr = pClassFactory->CreateInstance(NULL, IID_IDiaDataSource, (void**)&data_source);
    if (FAILED(hr))
        return hr;

    return S_OK;
}

Примечания:

  1. В вызове LoadLibrary вам может потребоваться указать путь. Не знаю, где обычно находится MSDIA100.DLL.

  2. Я не знаю, что делает MSDIA100.DLL. Не все COM-библиотеки будут работать с этим методом, особенно если они полагаются на беспоточный маршаллинг COM и подобные ужасные вещи. Однако большинство COM-DLL представляют собой простые многопоточные апартаменты и, по моему опыту, прекрасно работают.

8
ответ дан 18 December 2019 в 14:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: