Невозможно привести COM-объект типа "System.__ComObject" к интерфейсному типу...

Автор Тема: Невозможно привести COM-объект типа "System.__ComObject" к интерфейсному типу...  (Прочитано 22505 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Пишу модуль для AutoCAD 2014 на VB.NET, который просто перечисляет имена всех листов в текущем документе:

1. Код следующий:

Код - vb.net [Выбрать]
  1.  
  2. Imports System
  3. Imports System.Runtime.InteropServices
  4. Imports System.Windows.Forms
  5.  
  6. Imports Autodesk.AutoCAD.Interop
  7. Imports Autodesk.AutoCAD.Runtime
  8. ...
  9. Public ClassCheckProblem
  10.         <CommandMethod("JustCheckCOM")> _
  11.         Public Sub JustCheckCOM()
  12.             Dim acAppComObj As AcadApplication
  13.             acAppComObj = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication
  14.             Dim acDocComObj As AcadDocument
  15.             acDocComObj = acAppComObj.ActiveDocument
  16.  
  17.             For i = 0 To acDocComObj.Layouts.Count - 1
  18.                 MsgBox(acDocComObj.Layouts.Item(i).Name)
  19.             Next i
  20.         End Sub
  21. End Class
  22. ...
  23.  

2. Модуль подключаю к AutoCAD с помощью команды NETLOAD.
3. На компьютере, на котором модуль разрабатывался открывается и работает замечательно!
4. Стоит перенести этот модуль на другой компьютер - ВСЁ, ПРИЕХАЛИ... получаем следующее сообщение:




Что можно сделать в таком случае?









Подробная информация об использовании оперативной
(JIT) отладки вместо данного диалогового
окна содержится в конце этого сообщения.

************** Текст исключения **************
System.InvalidCastException: Невозможно привести COM-объект типа "System.__ComObject" к интерфейсному типу "Autodesk.AutoCAD.Interop.AcadApplication". Операция завершилась со сбоем, поскольку вызов QueryInterface COM-компонента для интерфейса с IID "{070AA05D-DFC1-4E64-8379-432269B48B07}" возвратил следующую ошибку: Интерфейс не поддерживается (Исключение из HRESULT: 0x80004002 (E_NOINTERFACE)).
   в ACAD_NET_PDF.ACADPDF.GetAFoo.football()
   в Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   в Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   в Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
   в Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()


Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Что-то было такое... Попробуйте заменить: Dim acAppComObj As AcadApplication на Dim acAppComObj As IAcadApplication

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Попробовал! IAcadApplication и даже IAcadDocument сделал )))

На моей машине работает, на чужой - увы, нет!

Может еще какое-нибудь решение есть

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Надо смотреть как библиотеки подключены, может там проблема...
А зачем через COM? Это же можно на чистом NET сделать.

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Проблема в том, что COM объект я знаю хорошо, а чистый NET - как китайская грамота ))) Но это пока, так-то я быстро учусь - учителя нет!

Подскажите, как бы вы сделали перебор всех листов в текущем чертеже и показали бы названия их установленных принтеров с помощью NET?

В случае VBA/ActiveX/COM это выглядело бы так:

Код - vb.net [Выбрать]
  1.     Public Class ShowPrintersAllLayouts
  2.         <CommandMethod("ShowPrinters")> _
  3.         Public Sub ShowPrinters()
  4.  
  5.             Dim acAppComObj As IAcadApplication
  6.  
  7.             acAppComObj = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication
  8.  
  9.             Dim acDocComObj As IAcadDocument
  10.  
  11.             acDocComObj = acAppComObj.ActiveDocument
  12.  
  13.             For i = 0 To acDocComObj.Layouts.Count - 1
  14.  
  15.                 MsgBox(acDocComObj.Layouts.Item(i).ConfigName)
  16.  
  17.             Next i
  18.  
  19.         End Sub
  20.     End Class


На компьютерах с установленным Visual Studio и AutoCAD это работает. На других - нет.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Подскажите, как бы вы сделали перебор всех листов в текущем чертеже и показали бы названия их установленных принтеров с помощью NET?
Наверное, на основе этого бы делал: http://through-the-interface.typepad.com/through_the_interface/2007/09/driving-a-basic.html
Для получения всех листов (имен), у меня есть такой вспомогательный метод:
Код - C# [Выбрать]
  1. /// <summary>
  2. /// Получение списка имен листов в чертеже
  3. /// </summary>
  4. /// <param name="db">База данных чертежа</param>
  5. /// <param name="noModel">true - список имен только листов, false - список имен листов и модели</param>
  6. /// <returns>Список имен листов</returns>
  7. public static string[] GetLayoutNames(this Database db, bool noModel = true)
  8. {
  9.     List<string> retVals = new List<string>();            
  10.     using (Transaction tr = db.TransactionManager.StartTransaction())
  11.     {
  12.         DBDictionary layoutDict = tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  13.         foreach (DBDictionaryEntry dbDictEnt in layoutDict)
  14.             retVals.Add(dbDictEnt.Key);
  15.         tr.Commit();
  16.     }
  17.  
  18.  
  19.     if (noModel)
  20.     {
  21.         //Удаляем из данных о листах модель            
  22.         retVals.Remove("Model");
  23.     }
  24.     return retVals.ToArray();
  25. }

Оффлайн Пашин ЕвгенийАвтор темы

  • ADN PRO
  • *
  • Сообщений: 662
  • Карма: 12
  • Skype: pashin.evgeniy
Ясно, вроде буквы знакомые, а только не понятно ничего... Что такое транзакция? Вообще для чего она нужна, какую роль она выполняет?

... OpenMode.ForRead - это зачем вообще? Типа получаем массив названий листов...
а если надо будет изменить имя листа, то надо будет выгрузить массив данных, изменить его, а потом загрузить массив в DBDictionary?
А где-то есть просто Layout(i).Name="Имя"? Без заморочек с какой-то транзакцией и т.д.?
Я даже не понял в какой строчке Вашего кода выводится название листа.

Мне же просто нужно подключиться к текущему чертежу и взять имена принтеров его листов...
Я не понимаю как это работает. Извини. Пятница - очень устал от безрезультатных действий.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Ну так это же азы NET программирования под автокад. Если планируется писать плагины для автокада на NET, то надо пройти базовое обучение. Благо, есть возможности и на тренинге это сделать (скоро AU2015Russia, обычно, в это же время тренинги для программистов проходят), и самостоятельно, например, с помощью таких материалов: http://usa.autodesk.com/adsk/servlet/index?id=18162650&siteID=123112
Конечно, если это разовая задача - то можно разобраться, почему COM не работает, исправить и остановиться на этом.

Оффлайн German

  • ADN Club
  • **
  • Сообщений: 84
  • Карма: 13
Как говорит автор прекрасного сайта https://sites.google.com/site/bushmansnetlaboratory/, RTFM.
Без обид, просто я начинал с этого. Тогда на русском материалов было очень мало.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Что такое транзакция? Вообще для чего она нужна, какую роль она выполняет?

... OpenMode.ForRead - это зачем вообще? Типа получаем массив названий листов...
а если надо будет изменить имя листа, то надо будет выгрузить массив данных, изменить его, а потом загрузить массив в DBDictionary?
А где-то есть просто Layout(i).Name="Имя"? Без заморочек с какой-то транзакцией и т.д.?
Я даже не понял в какой строчке Вашего кода выводится название листа.
А что, уже и гугл забанили? Не ленись юзать поиск: тынц, тынц.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
На компьютерах с установленным Visual Studio и AutoCAD это работает. На других - нет.
Обрати внимание на следующие моменты:
1. Компилировать обязательно в режим Release, а не Debug.
2. Версии AutoCAD должны совпадать.
3. Разрядность (x86/x64) AutoCAD должна совпадать (это в случае использования COM/Interop как у тебя.)
Если хотя бы одно из условий не выполняется - будет ошибка при выполнении.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Windcastle

  • ADN OPEN
  • **
  • Сообщений: 58
  • Карма: 0
Александр, спасибо за ответ. Это я Пашин Евгений. Пришлось зарегистрироваться заново. Буду писать с этого логина - из дома, с другого - с работы! Не пойму, почему меня не пускают на форум по рабочему логину )

1. Компилировать в режиме Release! Я правильно понимаю Вашу рекомендацию?



При сборке решения, папка Release - пустая! DLL сохраняется в папке Debug!

2. Версии AutoCAD должны совпадать!

AutoCAD 2014 для Windows 8.1 (x64) и AutoCAD 2014 для Windows XP (x64) - это я могу считать одинаковыми версиями?
Только у Windows XP NetFramework 4, а у Windows 8.1 NetFramework 4.5! Но компилирую под NetFramework 4!

3. Разрядность x64 у обеих машин!

Прошу Вас, сделайте то, что сделал я: код я выложил выше. Он ужасно простой. Попробуйте подгрузить библиотеку в AutoCAD на машине с установленным Visual Studio и на машине, где нет Visual Studio (даже пусть это будет другая машина - Windows 7 x64 к примеру). Если у Вас получится, то я больше не буду задавать Вам этот вопрос. И отстану! Приму тот факт, что это у меня какие-то проблемы с понимаем.

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


Код - vb.net [Выбрать]
  1. Public Class ShowPrintersAllLayouts
  2.         <CommandMethod("ShowPrinters")> _
  3.         Public Sub ShowPrinters()
  4.  
  5.             Dim acAppComObj As IAcadApplication
  6.  
  7.             acAppComObj = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication
  8.  
  9.             Dim acDocComObj As IAcadDocument
  10.  
  11.             acDocComObj = acAppComObj.ActiveDocument
  12.  
  13.             For i = 0 To acDocComObj.Layouts.Count - 1
  14.  
  15.                 MsgBox(acDocComObj.Layouts.Item(i).ConfigName)
  16.  
  17.             Next i
  18.  
  19.         End Sub
  20.     End Class



И еще! У меня дома стоит AutoCAD 2016 x64 - я принес эту библиотеку с работы, чтобы попробовать! Работает! Почему? И даже конфигурационный файл acad.exe.config не трогал.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Windcastle, Выложи полный проект (в zip-архиве).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Мне нужно решение, которое я смогу запускать на любых машинах, а не на отдельно взятой или с похожими характеристиками.
Этого сделать нельзя. Или тебе придётся извращаться с поздним связыванием или Reflection. Проще написать несколько dll-файлов в зависимости от версии и разрядности AutoCAD.
3. Разрядность x64 у обеих машин!
Точно? x64 на XP - это большая редкость.

При сборке решения, папка Release - пустая! DLL сохраняется в папке Debug!
Потому что активная конфигурация - DEBUG.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Не пойму, почему меня не пускают на форум по рабочему логину )
Или неверный логин, или неверный парооль. Других причин нет.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение