При активной разработке с использованием расширений конфигурации в экосистеме 1С:Предприятие разработчики часто сталкиваются с неприятной ошибкой. После добавления нового объекта (например, справочника, документа или константы) в расширение, программа отказывается запускаться или выдает критическую ошибку при попытке обращения к метаданным. Система сообщает, что для нового объекта не найден идентификатор в справочнике ИдентификаторыОбъектовМетаданных или в регистре сведений ИдентификаторыОбъектовВерсийРасширений.
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем внутренние механизмы Библиотеки стандартных подсистем (БСП) и рассмотрим несколько надежных способов её решения.
Для корректной работы механизмов разграничения прав доступа, бизнес-процессов и других служебных функций БСП хранит уникальные идентификаторы всех объектов конфигурации в справочнике ИдентификаторыОбъектовМетаданных. Для объектов из расширений предусмотрен отдельный механизм синхронизации с использованием регистра сведений ИдентификаторыОбъектовВерсийРасширений.
Когда мы пытаемся обновить вспомогательные данные (например, запуская конфигурацию с параметром /C ЗапуститьОбновлениеИнформационнойБазы), БСП обращается к функции СвойстваКоллекцийОбъектовМетаданных(), которая расположена в модуле менеджера справочника ИдентификаторыОбъектовМетаданных.
В этой функции жестко описана таблица свойств для всех коллекций метаданных. В зависимости от версии БСП, для многих коллекций объектов (особенно для констант, планов обмена, бизнес-процессов) по умолчанию выключен признак поддержки расширений. В коде это выглядит так: для свойства ОбъектыРасширений установлено значение Ложь. Из-за этого стандартный механизм обновления БСП просто игнорирует ваши новые объекты из расширения и не заносит их в системные справочники.
Чтобы решить проблему раз и навсегда без снятия основной конфигурации с поддержки, мы можем использовать механизм расширений. Нам потребуется перехватить выполнение функции СвойстваКоллекцийОбъектовМетаданных() с помощью директивы &Вместо.
Выполним следующие шаги:
ИдентификаторыОбъектовМетаданных и перенесем его модуль менеджера.СвойстваКоллекцийОбъектовМетаданных().Проанализируем пример кода, который принудительно включает поддержку расширений для необходимых нам типов объектов (например, для констант и справочников):
&Вместо("СвойстваКоллекцийОбъектовМетаданных")
Функция ИР_СвойстваКоллекцийОбъектовМетаданных()
// Получаем таблицу свойств коллекций по умолчанию из типового алгоритма
ТаблицаКоллекций = ПродолжитьВызов();
// Перебираем строки и находим нужные нам типы метаданных
Для Каждого СтрокаКоллекции Из ТаблицаКоллекций Цикл
// Если это константы или справочники, разрешаем работу с ними в расширениях
Если СтрокаКоллекции.Имя = "Константы"
Или СтрокаКоллекции.Имя = "Справочники" Тогда
СтрокаКоллекции.ОбъектыРасширений = Истина;
КонецЕсли;
КонецЦикла;
Возврат ТаблицаКоллекций;
КонецФункции
После применения данного расширения БСП начнет видеть ваши новые объекты констант или справочников. Теперь запуск обновления данных успешно зарегистрирует их в системе.
Бывают ситуации, когда типовые обработки обновления утверждают, что «обновление не требуется». Это происходит потому, что версия конфигурации не изменилась. В таком случае мы можем запустить процесс обновления принудительно с помощью внешней обработки.
Создадим простую внешнюю обработку, добавим на форму кнопку и пропишем следующий код в её модуле на сервере:
&НаСервере
Процедура ПринудительноОбновитьДанныеНаСервере()
УстановитьПривилегированныйРежим(Истина);
// 1. Принудительно обновляем данные основного справочника идентификаторов
ПараметрыОбновления = Справочники.ИдентификаторыОбъектовМетаданных.ПараметрыОбновитьДанныеСправочника();
ПараметрыОбновления.ЗаписатьНовыеИдентификаторы = Истина;
ПараметрыОбновления.ПометитьНаУдалениеНеиспользуемые = Истина;
Справочники.ИдентификаторыОбъектовМетаданных.ОбновитьДанныеСправочника(ПараметрыОбновления);
// 2. Вызываем обновление идентификаторов объектов расширений БСП
Справочники.ИдентификаторыОбъектовРасширений.ОбновитьДанныеСправочника(Истина);
Сообщить("Вспомогательные данные расширений успешно обновлены!");
КонецПроцедуры
Обратите внимание, что данный код следует запускать в монопольном режиме (когда в базе нет других активных пользователей и фоновых заданий), чтобы избежать конфликтов блокировок таблиц СУБД.
Часто разработчики пытаются использовать параметр запуска /С ЗапуститьОбновлениеИнформационнойБазы, но не получают ожидаемого результата. Давайте разберем основные подводные камни этого подхода:
C в параметре запуска /C обязательно должен быть написан на латинице. Если вы случайно скопировали этот параметр из русскоязычного текста, где буква «С» является кириллической, платформа проигнорирует этот ключ и запустит систему в обычном пользовательском режиме без выполнения процедур обновления.Если вы разрабатываете решение для распределенной базы данных, помните важный нюанс. При передаче расширения из центрального узла в подчиненный, файлы метаданных применятся автоматически. Однако подчиненный узел может не запустить процедуру обновления вспомогательных данных самостоятельно.
В этом случае администраторы или пользователи подчиненного узла сразу же столкнутся с ошибками доступа. Чтобы этого избежать, после каждого приема изменений из центрального узла в подчиненной базе крайне рекомендуется выполнять принудительный запуск обновления идентификаторов программным путем (как описано в Решении 2) или через параметры командной строки.