arthur2 писал(а):1. Как мне открыть группу, зная путь? Как открыть проект - понятно. А вот если группу?
Так же, как и проект:
Function AddFromFile(PathName As String, [Exclusive As Boolean = False]) As VBNewProjects
Member of VBIDE.VBProjects
Adds or opens a project or group project and returns a collection of all projects added using AddFromFile.
Второй параметр должен быть True.
arthur2 писал(а):2. Как закрыть проект или группу так, чтобы бейсик предложил сохраниться?
Если без грязных трюков, а только через объектную модель, которую предоставляют Add-in'ам, то похоже, что никак.
Правда в том, что метод
VBProjects::Remove всегда проверяет, есть ли в проекте не сохранённые изменения, и
всегда пытается спросить, хочет ли пользователь их сохранить.
VBProjects::Remove вызывает
RemoveProject, та вызывает
_PromptSaveProject, та вызывает
_PromptSaveChanges. Последняя показывает знаменитый диалог.
В недрах VB IDE существует функция
VBDialogCover2, которая отвечает за показ любых (всех) диалогов, порождаемых с причастностью IDE. То есть это и диалог подтверждения сохранения, и диалог создания нового проекта, диалог Options, диалог About и даже диалоги MsgBox и InputBox, показываемые при работе выполняемых проектов или вызываемых из Immediate Pane. То есть функция, через которую проходят все запросы на показ диалога.
В этой функции есть код, который проверяет особый флаг
g_nInOLECall — если флаг стоит, порождения диалога не происходит, а вместо этого осуществляется немедленный возврат из функции (с кодом 1).
- VBDialogCover2_killer_branch.png (3.61 Кб) Просмотров: 1862
Флаг устанавливается (точнее инкрементируется/декрементируется) методами
VBDispatch::EnterOleFunc /
VBDispatch::ExitOleFunc.
Беда в том, что все методы объектной модели, доступные Add-In'ам, имеют «внутрянку», обёрнутую между парой вызовов
EnterOleFunc и
ExitOleFunc. В том числе и метод VBProjects::Remove, с помощью которого можно выгрузить проект, обёрнут в эту пару:
- VBProjects.Remove_internals.png (15.58 Кб) Просмотров: 1862
Из-за этого отображения диалога сохранения несохранённого не происходит.
У «грязных трюков» есть два направления хода мыслей:
- Менять предусмотренную логику работы VB IDE. Если заNOPить инструкцию JNZ ..., то прекрасно всё будет работать так, как ты хочешь. VB будет предлагать сохраниться, а зависимости от выбора между Yes, No и Cancel будет либо закрытие проекта с сохранением, либо закрытие без сохранения, либо отмена закрытия (что для меня немного удивительно, потому что я сначала считал, что именно из-за невозможности адекватной обработки нажатия на «Cancel» весь этот запрет и придуман). Что характерно, в случае нажатия «Cancel» никакой ошибки не выбрасывается, вызывающий код не получает информации о том, состоялось ли вообще удаление проекта из списка загруженных..
Главный минус: ряд сторонних плагинов может полагаться на существующие «правила игры» (догма, что обращения к объектной моделью не приведут к показу каких бы то ни было IDE-шных диалогов, и что обращения не могут быть отменены пользователем, потому что его никто не спрашивает, а значит, если ошибки не произошло, значит операция выполнилась успешно). Изменение правил игры может поломать работу таких плагинов.
- Не пользоваться объектной моделью, а делать закрытие проекта через обращение к меню, как будто это пользователь жмёт пунктик «File —> Remove Project».
Главный минус: геморрой с нахождением нужного пункта, ведь среда может быть руссифицированной, а пункт может быть вообще убран из меню «File» за счёт возможности делать «Customize».
- Менюшный пункт «Remove Project» и метод VBProjects::Remove — оба стекаются к функции RemoveProject. Если вызывать её напрямую, то не будет вызова EnterOleFunc и ExitOleFunc, а значит не будет установлен особый флаг, а значит ничего не помешает показу диалога, а проект будет удалён из IDE как если бы мы воспользовались пунктом меню. Да, эта функция не экспортируется, её придётся находить каким-то способом. Но в первом варианте «грязных трюков» надо находить место, которое надо NOP-ить. А здесь, в отличие от первого варианта, нет проблемы с совместимостью с другими плагинами.