При интеграции систем на базе 1С через механизм COM-соединения (COMConnector) разработчики часто сталкиваются с неприятной ошибкой: "Значение не является значением объектного типа". Эта ошибка возникает в тот момент, когда код пытается обратиться к общему модулю, у которого в свойствах не установлен флаг Внешнее соединение. Ситуация осложняется, если конфигурация находится на поддержке и изменять свойства объектов основной конфигурации нельзя, а попытка изменить это свойство через расширение блокируется системой контроля свойств.
В данной статье мы подробно разберем, почему возникает эта проблема, и рассмотрим несколько эффективных способов её решения, позволяющих сохранить конфигурацию на поддержке и обеспечить доступ к нужному функционалу.
Разберем внутреннюю механику работы 1С. Когда мы подключаемся к базе через V83.COMConnector, создается специальный сеанс, контекст которого ограничен флагом Внешнее соединение. Если у общего модуля этот флаг не установлен, то для COM-сеанса этот модуль просто "не существует" в пространстве имен. Попытка обращения к нему возвращает Неопределено, что и приводит к ошибке при попытке вызова функции.
Важно понимать: ограничение действует только на прямое обращение из внешнего соединения. Если же мы попадем внутрь серверного контекста через модуль, у которого эта галочка есть, то внутри него мы сможем обращаться к любым другим серверным модулям, независимо от наличия у них флага внешнего соединения. Это и есть ключ к решению задачи.
Это самый правильный и стабильный архитектурный способ. Многие пытаются заимствовать существующий модуль в расширение и изменить его свойства, но 1С выдает ошибку: "Значение контролируемого свойства ВнешнееСоединение не совпадает со значением в расширяемой конфигурации". Чтобы обойти это, мы создадим в расширении новый модуль.
Проанализируем алгоритм действий:
Р_ВнешниеВызовыПрокси.Рассмотрим пример кода в нашем новом модуле расширения:
// В расширении: ОбщийМодуль.Р_ВнешниеВызовыПрокси
Процедура ВыполнитьРасчетПрокси(Параметр1, Параметр2) Экспорт
// Здесь мы находимся в контексте сервера расширения.
// Нам доступны все серверные модули основной конфигурации.
// Вызываем модуль, у которого нет флага "Внешнее соединение":
МодульБезГалочки.ЦелеваяПроцедура(Параметр1, Параметр2);
КонецПроцедуры
Теперь из внешнего приложения (например, из другой базы 1С или скрипта) мы будем обращаться не к МодульБезГалочки, а к нашему новому модулю Р_ВнешниеВызовыПрокси. Поскольку у него флаг установлен, 1С позволит войти в него, а дальнейший вызов внутри сервера уже не будет блокироваться.
Если специфика задачи позволяет пожертвовать производительностью ради простоты реализации, можно изменить способ подключения. Разберем разницу:
В режиме Application контекст выполнения соответствует обычному пользователю. Если код доступен на сервере, он будет доступен и через COM-вызов в этом режиме, так как клиентское приложение имеет более широкий доступ к программному интерфейсу. Однако стоит помнить, что этот метод требует больше памяти и работает медленнее, так как инициализирует все настройки пользователя, параметры сеанса и начальные формы.
Проанализируем ситуацию, когда нам нужно вызвать код, который категорически отказывается работать в контексте внешнего соединения. Мы можем использовать механизм фоновых заданий. Фоновое задание всегда запускается в чистом контексте сервера, где флаг "Внешнее соединение" вообще не играет роли.
Для этого в любом доступном модуле (с флагом внешнего соединения) создадим функцию запуска:
Функция ЗапуститьОбработкуДанных(Параметры) Экспорт
ИмяМетода = "МодульБезГалочки.ЦелеваяПроцедура";
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(Параметры);
Задание = ФоновыеЗадания.Выполнить(ИмяМетода, МассивПараметров);
Задание.ОжидатьЗавершения();
Возврат Истина;
КонецФункции
Этот метод позволяет полностью абстрагироваться от ограничений COM-сессии, переводя выполнение в полноценный серверный поток. Результат выполнения можно передать обратно через ВременноеХранилище или записав данные в справочник/регистр сведений.
Если мы не хотим вносить изменения даже в расширение, можно воспользоваться "лазейкой" с внешними обработками. Посмотрим на этот пример. Если во внешнем соединении нам доступен хотя бы один метод, позволяющий вызвать ВнешниеОбработки.Создать(), мы можем динамически загрузить обработку, в коде которой прописан вызов нужного модуля.
Рассмотрим шаги выполнения:
.epf), где в модуле объекта прописан вызов целевой функции.Поскольку код внешней обработки выполняется на стороне сервера, для него доступны все экспортные методы всех общих модулей конфигурации, независимо от их флагов доступа для COM.
Выясним, почему современная разработка уходит от COM-соединений. COM — это технология, сильно зависящая от разрядности систем (32/64 бит) и регистрации библиотек в реестре Windows. Более надежным способом является создание HTTP-сервиса в расширении.
HTTP-сервис работает по протоколу REST. Вы создаете в расширении объект HTTP-сервис, описываете в нем Шаблон URL и метод POST или GET. В обработчике этого метода вы вызываете любые функции любых модулей. Для системы это будет обычный серверный вызов. Вызывающая сторона использует объект HTTPСоединение, получает данные в формате JSON и не зависит от ограничений модулей 1С на внешнее соединение.
Подводя итог, можно выделить следующие правила выбора решения:
Главное — помните, что ограничение флага "Внешнее соединение" — это лишь преграда на входе в систему. Как только выполнение кода переходит под управление серверного контекста 1С через разрешенную "точку входа", все остальные модули становятся доступными для вызова.