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