ADN Open CIS
Сообщество программистов Autodesk в СНГ

15/04/2015

CreateInstance возвращает E_NOINTERFACE при обращении к экземпляру AutoCAD

Когда мы пытаемся запустить экземпляр AutoCAD из внешнего приложения используя функцию CreateInstance, иногда мы получаем ошибку E_NOINTERFACE. В этой статье мы рассмотрим некоторые причины, по которым это может происходить и пути решения этой проблемы.

Пожалуйста, не забывайте, что для построения версий 32 и 64 бит вашего внешнего приложения требуется импортировать соответствующие версии acax20ENU.tlb. GUID’ы отличаются в 32-ух и 64-ех битных версиях acax20ENU.tlb и поэтому не могут быть взаимозаменяемы.

Также при построении exe-файла, постарайтесь указать абсолютный путь для #import. Это будет гарантией того, что правильная версия tlb-файла будет импортирована в проект.

Например, для построения 32-ух битной версии exe-файла:

Код - C++: [Выделить]
  1. #import "D:\ObjectARX 2016\inc-win32\acax20ENU.tlb" no_implementation raw_interfaces_only named_guids

И соответственно для 64-ех битной версии:

Код - C++: [Выделить]
  1. #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 . Следующая строка должна помочь с этим:

Код - C++: [Выделить]
  1. ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

Другой причиной для ошибки E_NOINTERFACE может быть путаница между импортируемым tlb-файлом и CLSID используемым в CreateInstance. Например, если вы импортируете acax20ENU.tlb, то CLSID должно быть "AutoCAD.Application.20", что соответствует AutoCAD 2015 и 2016.

Вот пример для вызова экземпляра AutoCAD 2016:

 

Код - C++: [Выделить]
  1. #include  <acadi.h>
  2.  
  3.  #pragma  warning ( disable  : 4278 )
  4.  // Сделайте изменения в имени tlb
  5.  // в зависимости от версии AutoCAD.  
  6.  #import  "D:\\ObjectARX 2016\\inc-x64\\acax20ENU.tlb"  \\
  7.         no_implementation raw_interfaces_only named_guids
  8.  using  namespace  AutoCAD;
  9.  #pragma  warning ( default  : 4278 )
  10.  
  11.  ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  12.  
  13.  CLSID clsidAcad;
  14.  HRESULT hr;
  15.  hr = ::CLSIDFromProgID(
  16.         L"AutoCAD.Application.20" ,
  17.         &clsidAcad);
  18.  if (FAILED(hr))
  19.  {
  20.         ::MessageBox(
  21.         m_hWnd,
  22.         _com_error(hr).ErrorMessage(),
  23.         L"Ошибка CLSIDFromProgID!" ,
  24.         MB_OK);
  25.         return ;
  26.  }
  27.  
  28.  OLECHAR* bstrGuid;
  29.  ::StringFromCLSID(clsidAcad, &bstrGuid);
  30.  
  31.  ::MessageBox(
  32.                m_hWnd,
  33.                bstrGuid,
  34.                L"Получили CLSID из ProgID !" ,
  35.                MB_OK);
  36.  
  37.  
  38.  LPUNKNOWN punkAcad = NULL;
  39.  HRESULT hr = S_OK;
  40.               
  41.  IAcadApplicationPtr   m_acPtr;
  42.  hr = m_acPtr.GetActiveObject(clsidAcad);
  43.  if (SUCCEEDED(hr))
  44.  {
  45.         ::MessageBox(
  46.         m_hWnd,
  47.         L"Успешно выполнено GetActiveObject" ,
  48.         L"Ok!" ,
  49.         MB_OK);
  50.  
  51.         m_acPtr->put_Visible(VARIANT_TRUE);
  52.  }
  53.  else
  54.  {
  55.         ::MessageBox(
  56.         m_hWnd,
  57.         L"Ошибка в GetActiveObject,  
  58.         Попробуем CreateInstance !",
  59.         L"GetActiveObject" ,
  60.         MB_OK);
  61.  
  62.         hr = m_acPtr.CreateInstance(
  63.                clsidAcad, NULL, CLSCTX_LOCAL_SERVER);
  64.  
  65.         if (SUCCEEDED(hr))
  66.         {
  67.                ::MessageBox(
  68.                m_hWnd,
  69.                L"Успешно выполнено CreateInstance" ,
  70.                L"Ok!" ,
  71.                MB_OK);
  72.  
  73.                m_acPtr->put_Visible(VARIANT_TRUE);
  74.         }
  75.         else
  76.         {
  77.                ::MessageBox(
  78.                m_hWnd,
  79.                _com_error(hr).ErrorMessage(),
  80.                L"Ошибка CreateInstance!" ,
  81.                MB_OK);
  82.                return ;
  83.         }
  84.  }
  85.  
  86.  if (punkAcad)
  87.         punkAcad->Release();
  88.  

Источник: http://adndevblog.typepad.com/autocad/2015/04/createinstance-returns-e_nointerface-when-invoking-autocad-instance.html

Автор перевода: Александр Ривилис

Обсуждение: http://adn-cis.org/forum/index.php?topic=2636

Опубликовано 15.04.2015