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

Статьи => Тестирование статей => Тема начата: Дмитрий Загорулькин от 28-08-2015, 00:20:24

Название: Это экземпляр (приложения) Civil 3D?
Отправлено: Дмитрий Загорулькин от 28-08-2015, 00:20:24
Автор оригинальной статьи: Augusto Goncalves (http://adndevblog.typepad.com/infrastructure/augusto-goncalves.html). Статья находится тут: http://adndevblog.typepad.com/infrastructure/2015/03/is-a-civil-3d-instance.html

Это .NET версия кода, размещенная моим коллегой (оригинал тут (http://adndevblog.typepad.com/autocad/2012/09/determine-product-of-autocad-family.html)), переработанная под Civil 3D наименования.
Когда мы получаем экземпляр запущенного (приложения) AutoCAD, мы не знаем, что это за вертикальный продукт, так как все они базируются на одной платформе. Чтобы определить, с чем мы имеем дело, мы должны как-то это проверить. И это как раз то, что делает этот код:
Код - vb.net [Выбрать]
  1. ' получение запущенного экземпляра AutoCAD (или вертикального решения)
  2. Dim acadApp As Object = GetObject(, "Autocad.Application")
  3.  
  4. ' это Civil 3D? Попробуем!
  5. Dim civilLandApp As Object
  6. Try
  7.   ' 10.4 обозначает 2015 версию
  8.   civilLandApp = acadApp.GetInterfaceObject
  9.                  ("AeccXUiLand.AeccApplication.10.4")
  10. Catch ex As Exception
  11.   Return ' не Civil 3D
  12. End Try
  13.  
  14. ' теперь мы знаем – это Civil 3D
  15. ' что-то делаем
И в C# будет в основном то же самое, за исключением того, что необходимо определиться:  когда использовать var, а когда dynamic. Приведенный выше код использует Object который позволяет позднее связывание. Если это ваш вариант, тогда используйте C#-эквивалент: dynamic (https://msdn.microsoft.com/library/dd264736.aspx).

От переводчика, версия для C#:
Код - C# [Выбрать]
  1. dynamic acadApp;
  2. try
  3. {
  4.     // получение запущенного экземпляра AutoCAD (или вертикального решения)
  5.     acadApp = Marshal.GetActiveObject("AutoCAD.Application");
  6. }
  7. catch
  8. {
  9.     // нет запущенного AutoCAD
  10.     return;
  11. }
  12.  
  13. // это Civil 3D? Попробуем!
  14. dynamic civilLandApp;
  15. try
  16. {
  17.     // 10.3 - для версии 2014,
  18.     // 10.4 - 2015,
  19.     // 10.5 - 2016
  20.     civilLandApp = acadApp.GetInterfaceObject
  21.         ("AeccXUiLand.AeccApplication.10.3");
  22. }
  23. catch
  24. {
  25.     // не Civil 3D
  26.     return;
  27. }
  28.  
  29. // теперь мы знаем – это Civil 3D
  30. // что-то делаем, например, выведем сообщение:
  31. System.Windows.Forms.MessageBox.Show("Это Civil 3D 2014!");
Название: Re: Это экземпляр (приложения) Civil 3D?
Отправлено: Александр Ривилис от 28-08-2015, 00:35:27
Отлично! Есть еще соображения, которые позволили бы уточнить версию. Так как Civil 3D версии 20XX основан на AutoCAD версии 20XX, то можно сначала проверить Autodesk.AutoCAD.ApplicationServices.Application.Version.
Например, для 2014:
Код - C# [Выбрать]
  1. Autodesk.AutoCAD.ApplicationServices.Application.Version.Major == 19 &&
  2. Autodesk.AutoCAD.ApplicationServices.Application.Version.Minor == 1
для 2015:
Код - C# [Выбрать]
  1. Autodesk.AutoCAD.ApplicationServices.Application.Version.Major == 20 &&
  2. Autodesk.AutoCAD.ApplicationServices.Application.Version.Minor == 0
Название: Re: Это экземпляр (приложения) Civil 3D?
Отправлено: Дмитрий Загорулькин от 28-08-2015, 09:47:35
Тогда, раз уж мы через COM работаем, наверное, надо как-то так?:
Код - C# [Выбрать]
  1. dynamic acadApp;
  2. try
  3. {
  4.     // /Получение запущенного экземпляра AutoCAD (или вертикального решения)
  5.     acadApp = Marshal.GetActiveObject("AutoCAD.Application");
  6. }
  7. catch
  8. {
  9.     // Нет запущенного AutoCAD
  10.     return;
  11. }
  12.  
  13. // Получение номера версии AutoCAD
  14. string acVer = acadApp.Version.Substring(0, 4);
  15.  
  16. // Получение номера версии Aecc библиотек
  17. string aeccVer;
  18.  
  19. if (acVer == "19.0")
  20.     aeccVer = "10.0";
  21. else if (acVer == "19.1")
  22.     aeccVer = "10.3";
  23. else if (acVer == "20.0")
  24.     aeccVer = "10.4";
  25. else if (acVer == "20.1")
  26.     aeccVer = "10.5";
  27. else aeccVer = null;
  28.  
  29. if (string.IsNullOrEmpty(aeccVer))
  30. {
  31.     // Неизвестная версия AutoCAD
  32.     return;
  33. }
  34.  
  35. // это Civil 3D? Попробуем!
  36. dynamic civilLandApp;
  37. try
  38. {                
  39.     civilLandApp = acadApp.GetInterfaceObject
  40.         ("AeccXUiLand.AeccApplication." + aeccVer);
  41. }
  42. catch
  43. {
  44.     // не Civil 3D
  45.     return;
  46. }
  47.  
  48. // теперь мы знаем – это Civil 3D
  49. // что-то делаем, например, выведем сообщение:
  50. System.Windows.Forms.MessageBox.Show
  51.     (string.Format("Это {0}!", civilLandApp.Name));
  52.  
Название: Re: Это экземпляр (приложения) Civil 3D?
Отправлено: Александр Ривилис от 28-08-2015, 14:12:16
Отлично! Опубликовал как статью на сайте: Это экземпляр приложения Civil 3D? (http://adn-cis.org/eto-ekzemplyar-prilozheniya-civil-3d.html)
Название: Re: Это экземпляр (приложения) Civil 3D?
Отправлено: Андрей Бушман от 26-11-2015, 23:41:14
Можно определить версию, локализацию и полное имя AutoCAD (или любого его вертикального продукта) путём анализа значения свойства
Код - C# [Выбрать]
  1. Autodesk.AutoCAD.DatabaseServices.HostApplicationServices.Current.MachineRegistryProductRootKey
Я показывал (https://bitbucket.org/Andrey-Bushman/acadkeyparser/wiki/Home), как это делается. Причём такой подход позволяет получить искомую информацию не только из кода плагина, но и из кода любого стороннего приложения, не являющегося плагином AutoCAD.
Название: Re: Это экземпляр (приложения) Civil 3D?
Отправлено: Александр Ривилис от 10-01-2019, 00:25:24
Дмитрий Загорулькин,
Похоже если на одном компьютере установлен и Civil3D и Map3D одной версии, то код в случае Map3D идентифицирует запущенный экземпляр как Civil3D, что неправильно: https://forums.autodesk.com/t5/net/autocad-app-version-references/m-p/8511494/highlight/true#M61200
В качестве альтернативы я предложил проверять AppDomain.CurrentDomain.GetAssemblies() на наличие в нём "AeccDbMgd" и если нет, то пытаться его загрузить через Assembly.LoadFile, не забыв окаймить код в try/catch.