Всем привет!
Возникла проблема при которой созданная с помощью ActiveQt Add-In библиотека отказывалась добавляться в PDM. Ругалось на отсутствие реализованного интерфейса. Путём разбирания исходников и напихивания их отладочными МессаджБоксами было выявлено что загрузка не происходит из за того что после выполнения функции DllRegisterServer не происходит выполнение функции DllGetClassObject.
Как я понимаю схема работы такая:
После регистрации сервера (DllRegisterServer) клиент получает имеющиеся у сервера классы и начинает опрашивать их передавая в функцию DllGetClassObject.
Соответственно если функция DllGetClassObject не выполняется значит проблема с записями в реестре которые сервер делает в качестве регистрации в функции DllRegisterServer. Вот тут то и было потрачено большее количество времени и выделенных на эту проблему. Дело в том что все записи создаются. В итоге причину проблемы выяснить не удалось, но решается она ручной перезаписью значения ветки HKCR\CLSID\{НАШ UUID}\InProcServer32
После этого загрузка пошла дальше и ошибка изменилась и звучала она примерно так: «Эта библиотека имеет однопоточную модель STA (Single threading), а нам нужна мультипоточная MTA (Multi threading). Слава богу хоть в этот раз сайт документации майкрософт не подвёл и выдал страницу In-Process Server Threading Issues на которой было написано что InProcess OLE серверы не производят программных манипуляций для указания своей модели поточности (например с помощью функций CoInitializeEx(0, COINIT_MULTITHREADED) ), а вместо этого просто указывают это в реестре.
В итоге получился такой вот патч-костыль для личного пользования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
diff --git a/src/activeqt/control/qaxserver.cpp b/src/activeqt/control/qaxserver.cpp index 45f6940..25659d3 100644 --- a/src/activeqt/control/qaxserver.cpp +++ b/src/activeqt/control/qaxserver.cpp @@ -325,7 +325,21 @@ HRESULT UpdateRegistry(BOOL bRegister) if (insertable) settings->setValue(key + QLatin1String("/Insertable/."), QVariant(QLatin1String(""))); if (file.endsWith(QLatin1String("dll"), Qt::CaseInsensitive)) + { + wchar_t szInproc[MAX_PATH]=L"", szClsid[MAX_PATH]=L"", szBoth[]=L"Both"; + classId.toWCharArray(szClsid); + swprintf_s(szInproc, MAX_PATH,L"clsid\\%s\\InprocServer32",szClsid); + + HKEY hk; + if (ERROR_SUCCESS == RegCreateKey(HKEY_CLASSES_ROOT,szInproc,&hk) ) + { + RegSetValueEx(hk, NULL, 0, REG_SZ, (CONST BYTE *)qAxModuleFilename, (wcslen(qAxModuleFilename) * sizeof(wchar_t)) + 1); + RegSetValueEx(hk, L"ThreadingModel", 0, REG_SZ, (CONST BYTE *)szBoth ,(wcslen(szBoth) * sizeof(wchar_t)) + 1); + RegCloseKey(hk); + } settings->setValue(key + QLatin1String("/InProcServer32/."), file); + settings->setValue(key + QLatin1String("/InProcServer32/ThreadingModel"), QVariant(QLatin1String("Both"))); + } else settings->setValue(key + QLatin1String("/LocalServer32/."), QLatin1Char('\"') + file + QLatin1String("\" -activex")); |
По всем вопросам пишите в комментариях или на почту.
Спасибо за внимание!