Почему в 1С 7.7 не сохраняются константы после загрузки внешней компоненты FormEx?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке и сопровождении конфигураций на платформе 1С:Предприятие 7.7 разработчики часто сталкиваются с нестандартным поведением системы при подключении внешних библиотек. Типичная ситуация: простая операция установки значения константы перестает работать без выдачи каких-либо явных ошибок.

Рассмотрим конкретный пример кода, который вызывается для сохранения настройки:


Константа.SmtpСервер = SmtpСервер;
// или метод:
// Константа.SmtpСервер.Установить(SmtpСервер);

При этом наблюдается странная картина: если отключить загрузку внешней компоненты FormEx.dll, значение успешно сохраняется в базу данных. Стоит подключить FormEx в процедуре ПриНачалеРаботыСистемы() — и метод присвоения значения константе перестает производить запись, хотя на чистой типовой базе проблема может не воспроизводиться. Разберем по шагам механизм возникновения этой проблемы и выясним, как правильно её устранить.

Механизм возникновения проблемы и влияние FormEx

Проанализируем внутреннее устройство работы FormEx. При загрузке этой внешней компоненты в платформе активируются хуки (низкоуровневые перехватчики) движка блокировок 1С 7.7. Любая штатная попытка записи значения константы вызывает внутреннюю блокировку таблицы констант (_1SCONST), что автоматически инициирует вызов предопределенного события глобального модуля конфигурации:


Процедура ПриНачалеБлокировкиОбъекта(Объект)
    // Обработчик события перехвата блокировки
КонецПроцедуры

Здесь кроются две важные особенности, о которых необходимо знать каждому разработчику:

  1. Особенность параметра для констант: при блокировке справочников или документов параметр Объект передает ссылку на соответствующий объект данных. Однако при блокировке константы FormEx передает в качестве параметра обычную строку с идентификатором константы (ТипЗначенияСтр(Объект) = "Строка").
  2. Коллизия контекста блокировок ядра: событие ПриНачалеБлокировкиОбъекта выполняется платформой в момент низкоуровневой подготовки к фиксации блокировки. Если внутри этого обработчика происходит любое штатное чтение или запись другой константы (или работа с метаданными через встроенный язык), целостность цепочки вызовов ядра 1С нарушается. Платформа молча сбрасывает текущую операцию блокировки и транзакцию без выдачи синтаксической ошибки, из-за чего сохранение константы отменяется.

Способ 1. Проверка типа объекта в обработчике блокировок

Разберем самое правильное и надежное решение проблемы. Если в конфигурации используется процедура ПриНачалеБлокировкиОбъекта (например, для логирования действий пользователей или предотвращения параллельного редактирования), необходимо в самом начале процедуры поставить проверку типов и отсекать объекты, не являющиеся документами или справочниками.

Посмотрим на пример корректного кода глобального модуля:


Процедура ПриНачалеБлокировкиОбъекта(Объект)
    Тип = ТипЗначенияСтр(Объект);
    Если (Тип <> "Документ") И (Тип <> "Справочник") Тогда
        Возврат;
    КонецЕсли;
    
    // Код обработки блокировок для справочников и документов
КонецПроцедуры

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

Способ 2. Исключение штатных обращений к БД внутри событий FormEx

Если в процедурах ПриНачалеБлокировкиОбъекта или ОбработкаБлокировкиОбъекта требуется вести журнал пользователей, заблокировавших объекты, категорически нельзя обращаться к объектам метаданных через штатные методы 1С (такие как чтение констант или поиск в служебных справочниках). Всю запись служебной информации следует выносить либо во внешние структуры (текстовые лог-файлы), либо осуществлять запись напрямую через внешние компоненты прямого доступа к базе данных.

Способ 3. Корректный порядок инициализации внешних компонент

Посмотрим на типовой блок загрузки внешних компонент в процедуре ПриНачалеРаботыСистемы(). При совместном использовании нескольких библиотек (таких как 1C++, FormEx и сетевых модулей) критически важно соблюдать последовательность загрузки:


Процедура ПриНачалеРаботыСистемы()
    // 1. Базовые расширения ядра загружаем в первую очередь
    Если ЗагрузитьВнешнююКомпоненту("1cpp.dll") = 0 Тогда
        Сообщить("Не удалось загрузить 1cpp.dll");
    КонецЕсли;
    
    // 2. Библиотеки интерфейсных перехватов и событий
    Если ЗагрузитьВнешнююКомпоненту("FormEx.dll") = 0 Тогда
        Сообщить("Не удалось загрузить FormEx.dll");
    КонецЕсли;
КонецПроцедуры

Соблюдение порядка инициализации и контроль логики внутри системных обработчиков событий FormEx гарантирует стабильную запись констант и корректную работу транзакций в 1С:Предприятии 7.7.

← На главную