CreateInstance возвращает E_NOINTERFACE при обращении к экземпляру AutoCAD
Когда мы пытаемся запустить экземпляр AutoCAD из внешнего приложения используя функцию CreateInstance, иногда мы получаем ошибку E_NOINTERFACE. В этой статье мы рассмотрим некоторые причины, по которым это может происходить и пути решения этой проблемы.
Пожалуйста, не забывайте, что для построения версий 32 и 64 бит вашего внешнего приложения требуется импортировать соответствующие версии acax20ENU.tlb. GUID’ы отличаются в 32-ух и 64-ех битных версиях acax20ENU.tlb и поэтому не могут быть взаимозаменяемы.
Также при построении exe-файла, постарайтесь указать абсолютный путь для #import. Это будет гарантией того, что правильная версия tlb-файла будет импортирована в проект.
Например, для построения 32-ух битной версии exe-файла:
- #import "D:\ObjectARX 2016\inc-win32\acax20ENU.tlb" no_implementation raw_interfaces_only named_guids
И соответственно для 64-ех битной версии:
- #import "D:\ObjectARX 2016\inc-x64\acax20ENU.tlb" no_implementation raw_interfaces_only named_guids
Если абсолютный путь не задан, то может случиться, что tlb-файл будет найден из пути типа "C:\Program Files\Common Files\Autodesk Shared" и где находится в 64-битной системе 64-битная версия tlb-файла. Это может вызвать проблемы при использовании на 32-разрядной системе и привести в результате к ошибке E_NOINTERFACE.
Кроме того, с общей точки зрения для COM, вызывающий поток должен быть STA . Вы можете обеспечить это при помощи ::CoInitializeEx . Следующая строка должна помочь с этим:
- ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
Другой причиной для ошибки E_NOINTERFACE может быть путаница между импортируемым tlb-файлом и CLSID используемым в CreateInstance. Например, если вы импортируете acax20ENU.tlb, то CLSID должно быть "AutoCAD.Application.20", что соответствует AutoCAD 2015 и 2016.
Вот пример для вызова экземпляра AutoCAD 2016:
- #include <acadi.h>
- #pragma warning ( disable : 4278 )
- // Сделайте изменения в имени tlb
- // в зависимости от версии AutoCAD.
- #import "D:\\ObjectARX 2016\\inc-x64\\acax20ENU.tlb" \\
- no_implementation raw_interfaces_only named_guids
- using namespace AutoCAD;
- #pragma warning ( default : 4278 )
- ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
- CLSID clsidAcad;
- HRESULT hr;
- hr = ::CLSIDFromProgID(
- L"AutoCAD.Application.20" ,
- &clsidAcad);
- if (FAILED(hr))
- {
- ::MessageBox(
- m_hWnd,
- _com_error(hr).ErrorMessage(),
- L"Ошибка CLSIDFromProgID!" ,
- MB_OK);
- return ;
- }
- OLECHAR* bstrGuid;
- ::StringFromCLSID(clsidAcad, &bstrGuid);
- ::MessageBox(
- m_hWnd,
- bstrGuid,
- L"Получили CLSID из ProgID !" ,
- MB_OK);
- LPUNKNOWN punkAcad = NULL;
- HRESULT hr = S_OK;
- IAcadApplicationPtr m_acPtr;
- hr = m_acPtr.GetActiveObject(clsidAcad);
- if (SUCCEEDED(hr))
- {
- ::MessageBox(
- m_hWnd,
- L"Успешно выполнено GetActiveObject" ,
- L"Ok!" ,
- MB_OK);
- m_acPtr->put_Visible(VARIANT_TRUE);
- }
- else
- {
- ::MessageBox(
- m_hWnd,
- L"Ошибка в GetActiveObject,
- Попробуем CreateInstance !",
- L"GetActiveObject" ,
- MB_OK);
- hr = m_acPtr.CreateInstance(
- clsidAcad, NULL, CLSCTX_LOCAL_SERVER);
- if (SUCCEEDED(hr))
- {
- ::MessageBox(
- m_hWnd,
- L"Успешно выполнено CreateInstance" ,
- L"Ok!" ,
- MB_OK);
- m_acPtr->put_Visible(VARIANT_TRUE);
- }
- else
- {
- ::MessageBox(
- m_hWnd,
- _com_error(hr).ErrorMessage(),
- L"Ошибка CreateInstance!" ,
- MB_OK);
- return ;
- }
- }
- if (punkAcad)
- punkAcad->Release();
Обсуждение: http://adn-cis.org/forum/index.php?topic=2636
Опубликовано 15.04.2015