Почему возникает ошибка «Значение не является значением объектного типа» при COM-соединении между серверами 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

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

При этом ситуация часто сопровождается «плавающим» поведением: если запустить код на тестовом сервере — всё работает. Если все пользователи находятся на одном рабочем сервере — всё работает. Но как только нагрузка распределяется между двумя серверами кластера, COM-соединение начинает сбоить. Проанализируем эту ситуацию детально и разберем все возможные причины и методы решения.

Диагностика проблемы: куда пропадает COM-объект?

Давайте посмотрим на типичный кусок кода, на котором возникает сбой:


// Предполагается, что ВнешняяБаза - это успешно созданное COM-соединение
Подр_ЗУП = ВнешняяБаза.Справочники.ПодразделенияОрганизаций.ПустаяСсылка;

Если платформа выдает ошибку о том, что значение не является объектным типом, это означает только одно: переменная ВнешняяБаза в этот момент времени больше не содержит COM-объект. Как было отмечено в процессе отладки, эта переменная может внезапно содержать пустую ссылку на справочник, число, строку или тип Неопределено. Разберем по шагам, почему это происходит.

Решение 1: Проверка логики кода и случайной перезаписи

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

  1. Проверьте все места в коде, где используется переменная ВнешняяБаза (или та, в которой хранится соединение).
  2. Убедитесь, что нигде нет случайного присваивания вместо сравнения. Например, разработчик мог случайно написать ВнешняяБаза = ВнешняяБаза.Справочники.ПодразделенияОрганизаций.ПустаяСсылка.
  3. Используйте отладчик. Поставьте точку останова на строке успешного соединения и идите пошагово (F11), наблюдая за типом переменной в табло.

Решение 2: Потеря контекста и сериализация в кластере 1С

Рассмотрим более глубокую архитектурную проблему. COM-объекты в 1С:Предприятие существуют исключительно в оперативной памяти того конкретного рабочего процесса (rphost), в котором они были инициализированы.

Что происходит в кластере с несколькими рабочими серверами?

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

Как исправить: Никогда не передавайте COM-объекты между клиентом и сервером. Вся работа с COM-соединением (от установки подключения до чтения данных и закрытия соединения) должна происходить в рамках одного серверного вызова. Не сохраняйте COM-объекты в реквизиты формы, параметры сеанса или временное хранилище.

Решение 3: Изоляция COM-объекта через службы COM+

Если код отрабатывает в одном серверном вызове, но проблема сохраняется (особенно при кросс-серверном взаимодействии), давайте настроим изоляцию COM-компоненты на уровне операционной системы Windows. Вынос v83.COMConnector в отдельное приложение COM+ (Component Services) решает сразу множество проблем с правами и стабильностью.

Разберем по шагам, как это сделать:

  1. На сервере 1С откройте оснастку «Службы компонентов» (выполните команду dcomcnfg).
  2. Перейдите в ветку «Службы компонентов» -> «Компьютеры» -> «Мой компьютер» -> «Приложения COM+».
  3. Создайте новое пустое приложение (например, назовите его V83COM_App). Укажите тип активации — «Серверное приложение» (будет запускаться в отдельном процессе dllhost.exe).
  4. Перейдите в ветку «Компоненты DCOM» (или «Настройка DCOM»), найдите класс V83.COMConnector, зайдите в его свойства.
  5. На вкладке «Безопасность» настройте права доступа, запуска и активации, дав полные права пользователю, под которым работает служба сервера 1С (USR1CV8).
  6. Для созданного приложения COM+ на вкладке «Удостоверение» (Identity) укажите конкретную доменную учетную запись. Это решает проблему сетевых прав при обращении Сервера 1 к Серверу 2.
  7. Обязательно снимите флажок «Принудительная проверка доступа для приложения» (Enforce access checks for this application) на вкладке «Безопасность» приложения COM+, чтобы исключить скрытые блокировки ОС.

Решение 4: Отключение безопасного режима 1С

Проанализируем контекст выполнения вашего кода. Если процедура подключения к внешней базе запускается из внешней обработки, расширения или через фоновое/регламентное задание, платформа 1С может неявно активировать «Безопасный режим». В этом режиме платформа искусственно ограничивает возможности работы с COM-технологиями и внешними ресурсами.

Объект соединения может создаться, метод Connect вернет успешный результат, но при попытке получить свойства внешней базы платформа заблокирует доступ. Чтобы исключить эту причину, используйте явное отключение безопасного режима перед установкой соединения (если у вас есть на это права):


УстановитьБезопасныйРежим(Ложь);
// Далее инициализируем COM-объект
ВнешняяБаза = Новый COMОбъект("V83.COMConnector");
// ... код подключения ...

Решение 5: Сетевые настройки, DNS и IPv6

Посмотрим на сетевой уровень взаимодействия. Если серверы общаются друг с другом по сети, ОС Windows может использовать протокол IPv6 по умолчанию. Компонента DCOM иногда работает с ним нестабильно, из-за чего тяжелые вызовы (например, получение метаданных Справочники) отваливаются по таймауту.

Что мы можем предпринять:

  1. На обоих серверах откройте локальный файл C:\Windows\System32\drivers\etc\hosts.
  2. Пропишите жесткое соответствие IPv4-адресов и имен серверов кластера. Например:
    192.168.1.10 server1c-work1
    192.168.1.11 server1c-work2
  3. Убедитесь, что брандмауэр Windows (или сторонний антивирус) не блокирует динамические RPC-порты, которые использует DCOM для передачи данных.

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


Попытка
    Подр_ЗУП = ВнешняяБаза.Справочники.ПодразделенияОрганизаций.ПустаяСсылка;
Исключение
    ТекстОшибки = ОписаниеОшибки();
    ЗаписьЖурналаРегистрации("Обмен_COM", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
    Сообщить("Ошибка инициализации объекта: " + ТекстОшибки);
КонецПопытки;

Глобальная альтернатива: Переход на HTTP-сервисы

В завершение проанализируем перспективность используемой технологии. Технология COM-соединений является устаревшей и обладает рядом непреодолимых архитектурных недостатков:

Поэтому самым надежным и современным решением вашей задачи будет отказ от COM в пользу HTTP-сервисов или OData. REST API пишется один раз, работает поверх обычного протокола HTTP/HTTPS, не зависит от разности платформ на разных серверах, отлично балансируется в кластере и позволяет легко передавать данные в формате JSON или XML.

← На главную