Определение загруженных DVB
На самом деле вопрос носит полуакадемический характер: "можно ли определить лиспом, какие dvb-проекты загружены?" Естественно, можно!
Будем получать полные имена файлов dvb. Правда, этот код не скажет, какие функции и процедуры загружены, ну да ладно...
Снимем дамп с объекта приложения ACAD:
1 2 3 4 5 6 7 8 9 10 | _$ (vlax-dump-Object (vlax-get-acad-object)) ; IAcadApplication: An instance of the AutoCAD application ; Property values: <...> ; Preferences (RO) = #<VLA-OBJECT IAcadPreferences 000000000ed63b48> ; StatusId (RO) = ...Indexed contents not shown... ; VBE (RO) = #<VLA-OBJECT VBE 000000002ef0cfa8> ; Version (RO) = "17.2s (LMS Tech)" ; Visible = -1 <...> |
Есть тут одна интересная строка - VBE. Больно сильно напоминает Visual Basic Environment. Если продолжить ковыряться уже в этом свойстве, можно найти, что в нем хранятся записи обо всех загруженных dvb-приложениях. Следует помнить, что dvb загружаются не в пространство документа, а в пространство приложения AutoCAD.
Общая технология такова: получаем указатель на VBE, потом - на загруженные VBPorjects (проекты VBA), потом итерацией проходим по ним и для каждого элемента получаем его FileName:
1 2 3 4 5 6 7 8 9 10 11 12 | (vl-load-com) (defun get-dvb-loaded (/ lst res count) (if (setq lst (vlax-get (vla-get-vbe (vlax-get-acad-object)) "VBProjects")) (repeat (setq count (vla-get-count lst)) (setq res (cons (vla-get-filename (vla-item lst count)) res) count (1- count) ) ;_ end of setq ) ;_ end of repeat ) ;_ end of if (vl-sort res '<) ) ;_ end of defun |
Есть тут одна немного странная особенность: похоже, что индексация элементов начинается не с 0, а с 1 (!). И касается это любого наследника VBE!
Все это хорошо работает, если мы запускаем код в AutoCAD вплоть до 2009 версии, где VBA был интегрирован. А что будет, если запустить его, например, в AutoCAD 2014, где VBA может быть и не установлен?
При попытке выполнить строку вида (vla-get-VBE (vlax-get-acad-object)) мы получим сообщенеи об ошибке. Поэтому код надо немного переделать:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | (vl-load-com) (defun get-dvb-loaded (/ lst res count) (if (not (vl-catch-all-error-p (setq lst (vl-catch-all-apply (function (lambda () (vlax-get (vla-get-vbe (vlax-get-acad-object)) "VBProjects")) ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of setq ) ;_ end of vl-catch-all-error-p ) ;_ end of not (repeat (setq count (vla-get-count lst)) (setq res (cons (vla-get-filename (vla-item lst count)) res) count (1- count) ) ;_ end of setq ) ;_ end of repeat ) ;_ end of if (vl-sort res '<) ) ;_ end of defun |
Вот, теперь уже больше похоже на правду
В принципе, можно у каждого модуля получать не только его FileName, но и VBComponents (есть там такое свойство). Пройдя дальше, можно добраться до имен загруженных модулей (VBProjects, Collection) и даже попытаться что-то получать напрямую из кода. Правда, документации на это дело я не обнаружил (с другой стороны, особо и не искал).
---
На основе материлов из jtbworld.com. Но переделок и дополнений тут вполне прилично
Для примера в ACAD загрузил project.dvb (здесь сидит спецкалькулятор). Загрузил ваш лисп. В комстроке пишет:
2
3
4
Команда: (LOAD "D:/Work/Детали для AutoCAD/App_lisp/Проверка.lsp") GET-DVB-LOADED
Команда: (get-dvb-loaded)
no function definition: VLA-GET-FILENAME
Что пишу не так?
Последние лет 5 (если не больше) я к VBA имею очень опосредованное отношение - ну не нравится он мне!
Откуда взят dvb? Я специально взял первый попавшийся, тупо его загрузил и сразу выполнил код. Все сработало.
Может, дело в версии ACAD?