Как вызвать функцию общего модуля через внешнее соединение, если у него не установлена галочка Внешнее соединение

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

При интеграции систем на базе 1С через механизм COM-соединения (COMConnector) разработчики часто сталкиваются с неприятной ошибкой: "Значение не является значением объектного типа". Эта ошибка возникает в тот момент, когда код пытается обратиться к общему модулю, у которого в свойствах не установлен флаг Внешнее соединение. Ситуация осложняется, если конфигурация находится на поддержке и изменять свойства объектов основной конфигурации нельзя, а попытка изменить это свойство через расширение блокируется системой контроля свойств.

В данной статье мы подробно разберем, почему возникает эта проблема, и рассмотрим несколько эффективных способов её решения, позволяющих сохранить конфигурацию на поддержке и обеспечить доступ к нужному функционалу.

Почему возникает ошибка доступа к модулю

Разберем внутреннюю механику работы 1С. Когда мы подключаемся к базе через V83.COMConnector, создается специальный сеанс, контекст которого ограничен флагом Внешнее соединение. Если у общего модуля этот флаг не установлен, то для COM-сеанса этот модуль просто "не существует" в пространстве имен. Попытка обращения к нему возвращает Неопределено, что и приводит к ошибке при попытке вызова функции.

Важно понимать: ограничение действует только на прямое обращение из внешнего соединения. Если же мы попадем внутрь серверного контекста через модуль, у которого эта галочка есть, то внутри него мы сможем обращаться к любым другим серверным модулям, независимо от наличия у них флага внешнего соединения. Это и есть ключ к решению задачи.

Решение 1: Создание прокси-модуля в расширении

Это самый правильный и стабильный архитектурный способ. Многие пытаются заимствовать существующий модуль в расширение и изменить его свойства, но 1С выдает ошибку: "Значение контролируемого свойства ВнешнееСоединение не совпадает со значением в расширяемой конфигурации". Чтобы обойти это, мы создадим в расширении новый модуль.

Проанализируем алгоритм действий:

  1. Создадим в расширении конфигурации новый общий модуль, например, с именем Р_ВнешниеВызовыПрокси.
  2. В свойствах этого модуля обязательно установим флаги Сервер и Внешнее соединение. Также установим флаг Экспорт, если планируем вызывать его напрямую.
  3. Внутри этого модуля создадим экспортную процедуру-обертку, которая будет вызывать целевую функцию из "закрытого" модуля.

Рассмотрим пример кода в нашем новом модуле расширения:


// В расширении: ОбщийМодуль.Р_ВнешниеВызовыПрокси
Процедура ВыполнитьРасчетПрокси(Параметр1, Параметр2) Экспорт
    // Здесь мы находимся в контексте сервера расширения.
    // Нам доступны все серверные модули основной конфигурации.
    // Вызываем модуль, у которого нет флага "Внешнее соединение":
    МодульБезГалочки.ЦелеваяПроцедура(Параметр1, Параметр2);
КонецПроцедуры

Теперь из внешнего приложения (например, из другой базы 1С или скрипта) мы будем обращаться не к МодульБезГалочки, а к нашему новому модулю Р_ВнешниеВызовыПрокси. Поскольку у него флаг установлен, 1С позволит войти в него, а дальнейший вызов внутри сервера уже не будет блокироваться.

Решение 2: Использование V83.Application вместо COMConnector

Если специфика задачи позволяет пожертвовать производительностью ради простоты реализации, можно изменить способ подключения. Разберем разницу:

В режиме Application контекст выполнения соответствует обычному пользователю. Если код доступен на сервере, он будет доступен и через COM-вызов в этом режиме, так как клиентское приложение имеет более широкий доступ к программному интерфейсу. Однако стоит помнить, что этот метод требует больше памяти и работает медленнее, так как инициализирует все настройки пользователя, параметры сеанса и начальные формы.

Решение 3: Выполнение через фоновые задания

Проанализируем ситуацию, когда нам нужно вызвать код, который категорически отказывается работать в контексте внешнего соединения. Мы можем использовать механизм фоновых заданий. Фоновое задание всегда запускается в чистом контексте сервера, где флаг "Внешнее соединение" вообще не играет роли.

Для этого в любом доступном модуле (с флагом внешнего соединения) создадим функцию запуска:


Функция ЗапуститьОбработкуДанных(Параметры) Экспорт
    ИмяМетода = "МодульБезГалочки.ЦелеваяПроцедура";
    МассивПараметров = Новый Массив;
    МассивПараметров.Добавить(Параметры);
    
    Задание = ФоновыеЗадания.Выполнить(ИмяМетода, МассивПараметров);
    Задание.ОжидатьЗавершения();
    
    Возврат Истина;
КонецФункции

Этот метод позволяет полностью абстрагироваться от ограничений COM-сессии, переводя выполнение в полноценный серверный поток. Результат выполнения можно передать обратно через ВременноеХранилище или записав данные в справочник/регистр сведений.

Решение 4: Использование внешних обработок

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

Рассмотрим шаги выполнения:

  1. Подготавливаем внешнюю обработку (.epf), где в модуле объекта прописан вызов целевой функции.
  2. Через внешнее соединение передаем двоичные данные этой обработки или путь к ней.
  3. Создаем объект обработки на сервере и запускаем его метод.

Поскольку код внешней обработки выполняется на стороне сервера, для него доступны все экспортные методы всех общих модулей конфигурации, независимо от их флагов доступа для COM.

Решение 5: Переход на HTTP-сервисы

Выясним, почему современная разработка уходит от COM-соединений. COM — это технология, сильно зависящая от разрядности систем (32/64 бит) и регистрации библиотек в реестре Windows. Более надежным способом является создание HTTP-сервиса в расширении.

HTTP-сервис работает по протоколу REST. Вы создаете в расширении объект HTTP-сервис, описываете в нем Шаблон URL и метод POST или GET. В обработчике этого метода вы вызываете любые функции любых модулей. Для системы это будет обычный серверный вызов. Вызывающая сторона использует объект HTTPСоединение, получает данные в формате JSON и не зависит от ограничений модулей 1С на внешнее соединение.

Резюме и рекомендации

Подводя итог, можно выделить следующие правила выбора решения:

Главное — помните, что ограничение флага "Внешнее соединение" — это лишь преграда на входе в систему. Как только выполнение кода переходит под управление серверного контекста 1С через разрешенную "точку входа", все остальные модули становятся доступными для вызова.

← На главную