суббота, 10 ноября 2012 г.

Объектная модель "родной" регистрации плагинов для их автозагрузки в AutoCAD

В AutoCAD существует два способа добавления плагинов в автозагрузку:
  • Через реестр (старый способ).
  • С помощью файла PackageContents.xml (новый способ для новых версий AutoCAD).
"Новые" версии AutoCAD поддерживают оба способа регистрации автозагрузки.


В свою очередь регистрация в реестре может производиться в разных местах, разными способами:
  • HKEY_LOCAL_MACHINE\SOFTWARE\Autodesk\AutoCAD\R[CoreVersion]\ACAD-[ProductCode]:[LocalizationCode]\Applications
  • HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R[CoreVersion]\ACAD-[ProductCode]:[LocalizationCode]\Applications
  • HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R[CoreVersion]\ACAD-[ProductCode]:[LocalizationCode]\Profiles\[ProfileName]\Dialogs\Appload\Startup
Выполнить регистрацию программно не представляет никакого труда, однако программисту приходится писать некоторое количество кода, который проверяет наличие на машине необходимых версий AutoCAD их обновлений, а так же, если это необходимо - проверять различные настройки этих приложений. Ситуация несколько усложняется тем, что с выходом новых версий AutoCAD логика размещения информации в реестре и др. местах меняется и старый код перестаёт работать.

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

Дополнительно, в составе такой библиотеки можно было бы реализовать некоторую объектную модель, которой можно было бы пользоваться в различных целях:
  • Использование в самостоятельном приложении, которое управляет настройками автозагрузки для любых имеющихся на локальной машине версий AutoCAD посредством GUI.
  • Использование в инсталляторах/деинсталляторах.
  • Использование в генераторах отчётов, собирающих для администратора CAD необходимую статистику о настройках AutoCAD.
  • Управление регистрацией автозагрузки Вашего приложения из Вашего же кода.
Для решения обозначенной задачи мною была написана такая библиотека - AcadInfo.dll. Она может использоваться как в плагинах AutoCAD, так и в самостоятельных приложениях. К библиотеке прилагается CHM файл справки об объектной модели, а так же CHM файл справки с подробными примерами на тему того, как эту библиотеку следует использовать.

AcadInfo.dll - это не автозагрузчик, но на её основе (при желании) очень просто создать свою версию автозагрузчика, поскольку основной объем кода, необходимого для решения данной задачи, уже упакован в данную библиотеку. 

Если в дальнейшем логика регистрации плагинов в автозагрузку изменится, то достаточно будет перекомпилировать эту библиотеку и заменить ею более старые версии - сами приложения не придётся пересобирать. Помимо управлением автозагрузкой, библиотека предоставляет подробную информацию об установленных на компьютере всех версий AutoCAD и даёт возможность управлять их настройками, хранящимися в реестре.

Например, на основе AcadInfo.dll мною когда-то было написано некоторое GUI приложение, позволяющее управлять всеми доступными вариантами автозагрузки. Для наглядности показываю скрины:






Архив (библиотека + документация) выложены здесь.

Дата последнего обновления архива: 24.02.2014.
Перечень изменений:
1. Исправлена ошибка, из-за которой не удавалось использовать AcadInfo.dll в программах, скомпилированных как x86 и после этого запущенных на операционной системе x64.
2. Удалён перегруженный метод public static AcadInfo[] GetInstalledAutoCADs(String compName), предназначенный для получения информации об установленных на удалённой машине версиях AutoCAD (в виду трудоёмкости его качественной реализации).
3. Библиотека откомпилирована для .Net 3.5 SP1, .Net 4.0, .Net 4.5 с опцией AnyCPU.

В документацию изменения не вносились, поэтому следует учесть, что некоторая информация, представленная в ней, устарела.

20 комментариев:

Boxa комментирует...

Андрей, спасибо.
Очень востребовано.

Анонимный комментирует...

Правда востребовано.
Только вот справка на языке Оскара Уайлда не особо воспринимается)))
Есть переведенная? для неучей)

Андрей комментирует...

В исходном коде ресурсы разделены по локализациям. Сделано это как раз для того, чтобы можно было быстро добавлять новые локализации, банальным копированием ресурсного файла, с последующим переводом его содержимого. Однако по факту локализацию я сделал только для английского. На руссификацию ресурсного файла не нашёл времени, да и посчитал это лишним, т.к. в справке примеры и так достаточно понятные. В данном блоге ссылка дана не на самую свежую версию, т.к. некоторое время спустя я удалил из реализации этой библиотеки то, что касается работы с Bundle плагинами, решив вынести их в отдельный модуль. Решение обусловлено тем, что Autodesk меняет структуру указанного выше XML файла как перчатки. Кроме того, были найдены и исправлены какие-то ошибки (сейчас уж не помню, какие именно). Последнюю версию можно скачать отсюда (если мне память не изменяет...

bargool комментирует...

А вот и ответ, как надо обращаться к 64-х битной ветке реестра из 32-х битного приложения (а я компилировал приложение именно в этом режиме)
http://stackoverflow.com/a/13729137

Андрей Бушман комментирует...

Я и не спрашивал об этом. В обозначенном мною решении ветки реестра определяются корректно.

bargool комментирует...

вообще-то, я ещё 2 комментария отправлял. и последний мой комментарий - ответ на предыдущие 2 =)

Андрей Бушман комментирует...

не видел, возможно я их пропустил.

Alexander комментирует...

Я пытался использовать вашу библиотеку для написания своего регистратора плагинов для автокада. В Win7x32 все ок. Но в Win7x64 ничего не получилось. При вызове AcadInfo.GetInstalledAutoCADs валится с ошибкой:
System.ArgumentNullException: Значение не может быть неопределенным.
Имя параметра: acadRegistryKey
в AndreyBushman.AutoCAD.AcadInfo.GetServicePackRegistryKey(RegistryKey acadRegistryKey)
в AndreyBushman.AutoCAD.AcadInfo.GetAcadInfo(RegistryKey acadRegistryKey, String machineName)
в AndreyBushman.AutoCAD.AcadInfo.GetInstalledAutoCADs(String compName)
в AndreyBushman.AutoCAD.AcadInfo.GetInstalledAutoCADs()

Андрей Бушман комментирует...

1. Какие версии AutoCAD у вас установлены?
2. Все ли AutoCAD были хотя бы раз запущены после своей установки?

Alexander комментирует...

1. установлены Civil3D 2012 Rus и Civil3D 2014 Rus
2. запускались много раз

еще: перекомпилировал ехе для AnyCPU и сообщение пропало, но в списке установленных акадов - пусто. т.е. функция возвращает null

Андрей Бушман комментирует...

Сейчас у меня со временем напряг - ежедневно идёт обучение Revit. :( Осталось три занятия. Давайте вернёмся к вашей проблеме в следующий четверг: я просмотрю исходники и, если нужно, то могу их выложить в общий доступ.

Андрей Бушман комментирует...

>перекомпилировал ехе для AnyCPU и сообщение пропало

О каком EXE речь? Это ведь DLL...

Alexander комментирует...

ОК, подождать не проблема)

ЕХЕ - который содержит в себе форму для взаимодейтсвия с юзером (интерфейс регистратора плагинов в акад). Из него происходит вызов AcadInfo.GetInstalledAutoCADs

bargool комментирует...

Это именно то, о чем я говорил в пропавших комментариях.
При компиляции под 32 бита библиотека смотрит в 32х битных ветках реестра. А если система 64х битная, автокад зарегистрирован в 64х битной.
http://stackoverflow.com/a/13729137

Андрей Бушман комментирует...

Я в курсе об этом и в коде этот момент учтён. В четверг гляну исходники.

Андрей Бушман комментирует...

Александр, ты своё приложение как компилируешь: AnyCPU или же x86\x64?

Андрей Бушман комментирует...

В коде библиотеки я исходил из предположения, что приложение, использующее эту библиотеку, будет компилироваться как AnyCPU. Если же предложение компилируется как x86, после чего запускается под x64, то указанная тобой ошибка действительно возникает. Подправлю это.

Alexander комментирует...

Исправил на AnyCPU после появления описаной ошибки. В такой конфигурации (все копилируется для AnyCPU) cначало не определялись установленные автокады. Но похоже какая-то проблемма была у меня в тестовой системе. После переустановки автокадов - они стали определяються. Возможно какой-то патч (винды или акада) криво установился... сейчас глюк не повторяется на моей машине. Проверил еще на других WinXP x32, Win7 x32, Win7 x64 - все ок))

Андрей Бушман комментирует...

Я внёс изменение в файл AcadInfo.dll и добавил файл dev.dll, в котором реализовал независимость разрядности приложения от разрядности операционной системы (при работе с реестром). Ещё потестирую и затем результат выложу, но это уже на след. неделе, т.к. сегодня пятница + уже отмечаем предстоящий праздник.

Андрей Бушман комментирует...

Выложил и обновил ссылку.