Типовую обновили — и одно из расширений тихо перестало совпадать с конфигурацией. Список расширений в БСП при этом рисует ему зелёную галочку «подключено»: проверку применимости форма не выполняет. А расширению, которое администратор просто выключил, та же форма ставит красный крест с подписью «Не удалось подключить при входе в приложение». Чтобы узнать правду, приходится лезть в Конфигуратор или вспоминать, кто и когда снимал флажок.
Второй вопрос после обновления — что вообще меняют расширения в этой базе. Форма документа ведёт себя странно, реквизит взялся непонятно откуда — в каком расширении искать? Платформа умеет ответить и на это, но в стандартных формах ответа нет.
Обработка «Расширения в базе» собирает оба ответа в одном окне: состояние каждого расширения словами, проблемы применения с текстом платформы и дерево объектов конфигурации, которые расширения добавили или изменили — до реквизита и формы. Форма управляемая, работает только на методах платформы, поэтому открывается и в конфигурации без БСП. Если БСП есть, появляется ещё закладка с дополнительными отчётами и обработками. В базу обработка ничего не пишет, нужны права администратора.
Как это выглядит
Список расширений
Сверху — расширения с бедой: не подключившиеся и те, у которых проверка применимости нашла критичную проблему. Колонка «Что меняет» сразу говорит, сколько объектов расширение добавило и изменило. Под списком — полный текст проблем выбранного расширения.
«Доработка справочника банков» подключена, но проверка применимости нашла критичную проблему: копия метода в расширении больше не совпадает с методом конфигурацииТа же база в стандартной форме БСП «Расширения»: у этого расширения зелёная галочка, а у выключенных вручную «Отчётов руководителя» — красный крест «Не удалось подключить».
Для сравнения — стандартная форма «Расширения»: проблемное расширение выглядит подключённым, а выключенное — сломанным.Расширение, которое действительно не подключилось, обработка показывает с причиной — той, что назвала платформа.
«Вес товаров» включён, но не подключился: в конфигурации нет общей картинки, на которую он ссылаетсяЧто меняют расширения
На второй закладке — только затронутые объекты конфигурации: какие добавлены и каким расширением, какие изменены и что именно в них изменено — реквизит, табличная часть, форма, команда, макет.
Добавленный справочник, реквизит расширения в типовой «Номенклатуре», изменённые формы и состав подсистемыПлатформа считает изменёнными гораздо больше объектов, чем расширения трогали на самом деле. Флажок «Косвенные изменения» показывает их с объяснением, откуда взялась отметка.
Косвенные изменения: новый справочник расширения вошёл в составной тип реквизитов регистров и справочников БСП.Двойной щелчок по расширению в списке открывает дерево только с его объектами.
Отбор по одному расширению: реквизит «Заметка менеджера» в «Номенклатуре» и изменённая форма элементаДополнительные отчёты и обработки
Если в конфигурации есть справочник БСП «Дополнительные отчёты и обработки», появляется третья закладка. Отдельный отбор — обработки без безопасного режима: они работают с полными правами, и такие стоит знать наперечёт.

Как это сделано
Состояние расширения: три списка вместо одного
Словами состояние платформа не отдаёт. Обработка собирает его из трёх списков, которые возвращает РасширенияКонфигурации.Получить с разными источниками: всё, что установлено в базе, подключённое в текущем сеансе и не подключённое. Ключи сеансовых списков она складывает в соответствия, а потом проходит по расширениям базы:
Подключённые = КлючиРасширений(ИсточникРасширенийКонфигурации.СеансАктивные);
Отключённые = КлючиРасширений(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Расширение Из РасширенияКонфигурации.Получить() Цикл
Ключ = КлючРасширения(Расширение);
Если Подключённые[Ключ] <> Неопределено Тогда
Состояние = ?(Расширение.Активно, "подключено", "подключено, выключится после перезапуска");
ИначеЕсли Отключённые[Ключ] <> Неопределено Тогда
Состояние = ?(Расширение.Активно, "не подключилось", "выключено");
Иначе
Состояние = "ждёт перезапуска";
КонецЕсли;
КонецЦикла;
Функция КлючРасширения(Расширение)
Возврат Расширение.Имя + "|" + Расширение.ХешСумма + "|" + Расширение.ОбластьДействия;
КонецФункции
Ключ состоит из имени, хеша и области действия — так же сравнивает и форма БСП. Хеш здесь главный: расширение, которое обновили после входа, в сеансе работает ещё в прежней версии, и по одному имени обработка приняла бы его за подключённое. С хешем оно не находится ни в одном сеансовом списке и честно получает «ждёт перезапуска».
Выключенное вручную расширение лежит в списке не подключённых с Активно = Ложь, и обработка называет его выключенным. Форма БСП смотрит только на то, в каком списке расширение, поэтому и рисует ему «Не удалось подключить».
Не подключилось или просто ждёт входа
В списке не подключённых с Активно = Истина оказываются два разных случая. Первый — расширение не прошло проверку применимости и платформа его не подключила. Второй — флажок «Активно» поставили уже после входа в программу, и расширение подключится при следующем входе. Проверка применимости их и различает: у настоящего отказа есть критичная проблема.
Критичных = ОписатьПроблемы(Расширение, Запись);
Если Запись.КНеПодключилось И Критичных = 0 Тогда
Запись.КСостояние = "подключится после перезапуска";
Запись.КНеПодключилось = Ложь;
КонецЕсли;
Проблемы применения
Метод расширения ПроверитьВозможностьПрименения возвращает массив проблем: у каждой важность, текст и расширение, к которому она относится. Обработка вызывает его для каждого расширения, в том числе для подключённых, — именно там прячется самое интересное.
Попытка
Проблемы = Расширение.ПроверитьВозможностьПрименения();
Исключение
ЗаписьЖурналаРегистрации("Расширения в базе", УровеньЖурналаРегистрации.Ошибка, , ,
"Проверка применимости «" + Расширение.Имя + "»: " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат 1;
КонецПопытки;
Критичных = 0;
Тексты = Новый Массив;
Для Каждого Проблема Из Проблемы Цикл
Если Проблема.Важность = ВажностьПроблемыПримененияРасширенияКонфигурации.Критичная Тогда
Критичных = Критичных + 1;
КонецЕсли;
Тексты.Добавить(ВажностьСловами(Проблема.Важность) + ": " + Проблема.Описание);
КонецЦикла;
Типичный случай — метод с аннотацией &ИзменениеИКонтроль. Расширение хранит копию исходного метода, и после обновления типовой копия перестаёт совпадать с оригиналом. Я проверял на 8.5: такое расширение продолжает подключаться, а проверка возвращает критичную проблему «Текст метода … не соответствует методу …». Доработка работает, но опирается на старый код, и увидеть это можно только так.
Важность обработка сравнивает со значением перечисления, а не со строкой: строки платформы приходят на языке интерфейса, и в английской базе там будет другой текст. По той же причине назначение, область действия и безопасный режим обработка выводит своими словами.
Что добавлено и что изменено
У каждого объекта метаданных есть два метода. РасширениеКонфигурации() возвращает расширение, которое добавило объект, — или Неопределено, если объект из конфигурации. ЕстьИзмененияРасширениямиКонфигурации() отвечает, изменён ли объект расширениями. Обработка обходит все коллекции конфигурации и раскладывает объекты на добавленные и изменённые:
Для Каждого ИмяКоллекции Из СтрРазделить(КоллекцииМетаданных(), ",", Ложь) Цикл
Для Каждого ОбъектМД Из Метаданные[ИмяКоллекции] Цикл
Расширение = ОбъектМД.РасширениеКонфигурации();
Если Расширение <> Неопределено Тогда
Добавленные.Добавить(Новый Структура("Вид,Объект,Расширение", ИмяКоллекции, ОбъектМД, Расширение));
Если ТипыСсылок.Свойство(ИмяКоллекции) Тогда
ДобавленныеТипы.Добавить(Новый Структура("Тип,Объект,Расширение",
Тип(ТипыСсылок[ИмяКоллекции] + "." + ОбъектМД.Имя), ОбъектМД, Расширение));
КонецЕсли;
ИначеЕсли ОбъектМД.ЕстьИзмененияРасширениямиКонфигурации() Тогда
Изменённые.Добавить(Новый Структура("Вид,Объект,Путь", ИмяКоллекции, ОбъектМД, ""));
КонецЕсли;
КонецЦикла;
КонецЦикла;
Оба метода дешёвые: обход всей типовой конфигурации с ними занимает доли секунды, поэтому обработка строит дерево сразу при открытии. Попутно обработка запоминает ссылочные типы добавленных объектов — ТипыСсылок сопоставляет коллекции с именами типов, например «Справочники» с «СправочникСсылка». Эти типы нам понадобятся ниже, для косвенных изменений.
Вложенные подсистемы в коллекцию Метаданные.Подсистемы не входят, их обработка обходит рекурсией и подписывает путём «Продажи → Продажи».
Что именно изменено в объекте
Отметка «изменён» у справочника мало что говорит. Обработка спускается к его частям — реквизитам, табличным частям с их реквизитами, формам, командам, макетам — и спрашивает те же два метода у каждой части. Какие части бывают у объекта, она определяет по виду коллекции, а не перебором с исключениями.
Для Каждого ИмяЧастей Из СтрРазделить(ЧастиВида(Вид), ",", Ложь) Цикл
Для Каждого Часть Из ОбъектМД[ИмяЧастей] Цикл
Расширение = Часть.РасширениеКонфигурации();
Если Расширение = Неопределено И НЕ Часть.ЕстьИзмененияРасширениямиКонфигурации() Тогда
Продолжить;
КонецЕсли;
// строка под объектом: «добавлен расширением …» или «изменён»
КонецЦикла;
КонецЦикла;
Реквизит, который расширение добавило в типовой справочник, знает своё расширение — его дерево и показывает. Реквизиты, которые расширение только заимствовало, чтобы вывести форму, платформа изменёнными не считает, и в дерево они не попадают.
Каким расширением изменена форма или модуль, платформа не сообщает — только сам факт. Если объект трогают несколько расширений, такое изменение видно в дереве при отборе «Все расширения», но не при отборе по одному из них.
Косвенные изменения
Если расширение добавляет свой справочник, платформа считает изменёнными все объекты, у которых есть реквизит составного типа, куда этот справочник вошёл: «любая ссылка», значение дополнительного свойства и подобные. В типовой конфигурации с БСП это десятки регистров и справочников, которые расширение не трогало. Сами такие реквизиты платформа изменёнными не помечает — только объект.
Чтобы отделить шум от настоящих изменений, обработка проверяет у изменённого объекта без изменённых частей типы реквизитов:
Для Каждого Реквизит Из Реквизиты Цикл
Для Каждого Добавленный Из ДобавленныеТипы Цикл
Если Реквизит.Тип.СодержитТип(Добавленный.Тип) Тогда
Возврат Новый Структура("Текст,Расширение",
"тип «" + Реквизит.Имя + "» U92; «" + Добавленный.Объект.Синоним + "»",
Добавленный.Расширение.Имя);
КонецЕсли;
КонецЦикла;
КонецЦикла;
В Реквизиты обработка заранее собрала реквизиты, измерения, ресурсы и реквизиты табличных частей объекта. Нашёлся реквизит с типом из расширения — изменение косвенное, и обработка прячет его за флажок. Не нашёлся — изменён модуль или свойства объекта, и отметка остаётся на виду.
Дополнительные отчёты и обработки БСП
Справочник БСП чужой: в одной конфигурации его нет вовсе, в другой у него свой набор реквизитов. Поэтому обработка создаёт закладку, только если справочник есть, и берёт в запрос лишь те реквизиты, что в этой базе существуют. Право чтения обработка проверяет заранее, а не ловит исключение запроса.
СправочникМД = Метаданные.Справочники.ДополнительныеОтчетыИОбработки;
Если НЕ ПравоДоступа("Чтение", СправочникМД) Тогда
Возврат;
КонецЕсли;
Поля = Новый Массив;
Поля.Добавить("Т.Наименование КАК Наименование");
Поля.Добавить("Т.ПометкаУдаления КАК ПометкаУдаления");
Для Каждого Имя Из СтрРазделить("Вид,Версия,Публикация,БезопасныйРежим,ИмяФайла,Ответственный,Информация", ",") Цикл
Если СправочникМД.Реквизиты.Найти(Имя) = Неопределено Тогда
Поля.Добавить("NULL КАК " + Имя);
Иначе
Поля.Добавить("Т." + Имя + " КАК " + Имя);
КонецЕсли;
КонецЦикла;
Запрос = Новый Запрос("ВЫБРАТЬ " + СтрСоединить(Поля, ", ")
+ " ИЗ Справочник.ДополнительныеОтчетыИОбработки КАК Т"
+ ?(СправочникМД.Иерархический, " ГДЕ НЕ Т.ЭтоГруппа", ""));
Отключённую обработку нам нужно распознать по значению перечисления, которого в конфигурации без БСП нет. ЗНАЧЕНИЕ() в запросе и обращение к Перечисления в коде там не скомпилируются, а представление значения зависит от языка. Здесь помогает XMLСтрока: для значения перечисления она возвращает его имя.
Отключена = (XMLСтрока(Выборка.Публикация) = "Отключена");
На чём проверено
Я проверял на платформе 1С:Предприятие 8.5 (8.5.1.1522) и «Управлении нашей фирмой» 3.0 (3.0.14.143). В веб-клиенте, на серверной базе. Без БСП — на своей конфигурации, на той же платформе.
На 8.3 я не проверял. Может, откроется, а может, и нет.
Состав поставки
RasshireniyaVBaze.epf— внешняя обработка «Расширения в базе», код открыт.
Вступайте в нашу телеграмм-группу Инфостарт