В практике интеграции систем на платформе 1С:Предприятие 8.3 использование COM-соединения (есть универсальная обработка переноса данных через COM и HTTP) остается одним из самых распространенных способов обмена данными, часто дополняющим механизмы, где требуется универсальная регистрация справочников и документов к обмену. Однако программисты часто сталкиваются с ситуацией, когда соединение устанавливается успешно, но в процессе передачи данных или вызова методов процедур система «наглухо» зависает. Процесс rphost или клиентское приложение перестает отвечать, а отладка не дает результатов, так как точка останова в базе-источнике просто не срабатывает. Разберем детально, почему это происходит и как решить проблему.
Рассмотрим типичную ситуацию. У нас есть две базы: «Бухгалтерия предприятия» и «Управление торговлей» (поможет перенос документов из УТ 11 в БП 3.0 через COM Connector). Обмен запускается из одной базы, создается объект V83.COMConnector, выполняется метод Connect(), но при попытке вызвать экспортную функцию общего модуля (предварительно убедитесь, что в коде нет изъянов, используя анализ конфигураций и расширений на наличие ошибок) с передачей параметров (например, структуры настроек) поток выполнения останавливается.
Проанализируем причину. Основная ошибка кроется в маршаллинге объектов. Когда мы создаем объект Структура или Массив в текущей (клиентской) базе и передаем его как параметр в метод COM-соединения, 1С пытается передать этот объект «по ссылке» через границу процессов. База-приемник получает ссылку на объект, который физически находится в памяти базы-источника. При попытке прочитать свойства этой структуры база-приемник обращается обратно к источнику. Если в этот момент возникают проблемы с правами доступа, блокировками DCOM или сетевыми задержками, процесс зацикливается или переходит в состояние бесконечного ожидания (Deadlock).
Выясним основной секрет стабильной работы: сложные объекты должны создаваться в контексте той базы, к которой мы подключаемся. Вместо того чтобы передавать «свою» структуру, мы должны попросить внешнюю базу создать структуру внутри себя. Для этого используется метод NewObject() объекта COM-соединения.
Рассмотрим пример неправильного кода, который приводит к зависанию:
// ОШИБОЧНЫЙ ВАРИАНТ
ПараметрыОбмена = Новый Структура("КодУзла, ДатаВыгрузки", "001", ТекущаяДата());
// Здесь программа зависнет, так как ПараметрыОбмена созданы в текущей базе
Результат = БазаПриемник.МойОбщийМодуль.ВыполнитьОбмен(ПараметрыОбмена);
А теперь разберем корректный вариант реализации, который исключает зависание:
// ПРАВИЛЬНЫЙ ВАРИАНТ
// Создаем структуру непосредственно в базе-приемнике
ПараметрыОбмена = БазаПриемник.NewObject("Структура");
ПараметрыОбмена.Вставить("КодУзла", "001");
ПараметрыОбмена.Вставить("ДатаВыгрузки", ТекущаяДата());
// Теперь передача параметра пройдет мгновенно, так как объект "родной" для той базы
Результат = БазаПриемник.МойОбщийМодуль.ВыполнитьОбмен(ПараметрыОбмена);
Использование NewObject гарантирует, что объект Структура будет размещен в адресном пространстве процесса, обслуживающего базу-приемник. Это избавляет систему от необходимости постоянных «обратных» вызовов к базе-инициатору через COM-интерфейс — для этого есть готовый обмен данными между УТ и БП через COM.
Проанализируем ситуацию, когда код написан верно, но зависания продолжаются. В современных операционных системах, таких как Windows Server 2022, компания Microsoft внедрила усиленные проверки безопасности протокола DCOM (DCOM Hardening). Это может приводить к блокировкам неавторизованных вызовов между компонентами 1С.
Если вы столкнулись с зависанием на этапе Connect() или сразу после него, выполните следующие шаги:
comcntr.dll. Важно, чтобы версия зарегистрированной компоненты точно совпадала с версией сервера 1С. Используйте команду: regsvr32 "C:\Program Files\1cv8\8.3.25.1520\bin\comcntr.dll".dllhost.exe, что значительно повышает стабильность и упрощает диагностику (если соединение зависнет, можно «убить» только один dllhost.exe, не затрагивая весь сервер 1С). Для этой задачи есть настройка регулярного обмена данными между базами 1С.dcomcnfg. Учетная запись, под которой работает служба 1C:Enterprise Server, должна иметь права на «Локальный запуск» и «Локальную активацию» для компонентов 1С.Посмотрим на другие причины, которые могут имитировать зависание:
1. Модальные окна и предупреждения. Если в коде базы-приемника (например, в обработчике ПриУстановкеНовогоНомера или в общем модуле) вызывается метод Сообщить(), Вопрос() или Предупреждение(), COM-соединение может «замереть» в ожидании реакции пользователя, которой не может последовать в неинтерактивном режиме. Всегда используйте проверку #Если Не ВнешнееСоединение Тогда.
2. Ошибка формата потока. Эта ошибка часто возникает при попытке передать через COM объект типа ТаблицаЗначений или ХранилищеЗначения. Помните, что через COM-границу без проблем проходят только простые типы: Строка, Число, Дата, Булево. Для передачи сложных структур лучше использовать адаптивный перенос данных через XML или сериализацию в JSON.
3. Разрядность систем. Если ваш сервер 1С 64-битный, а вы пытаетесь подключиться к базе через 32-битную компоненту (или наоборот), система может вести себя непредсказуемо. Убедитесь, что в реестре прописаны правильные пути к 64-битной версии comcntr.dll.
Несмотря на то, что мы разобрали, как починить COM-соединение, важно понимать, что фирма 1С официально рекомендует уходить от этого механизма в пользу HTTP-сервисов. HTTP-обмен работает через стандартный порт 80/443, не требует настройки DCOM, не зависит от разрядности библиотек и не страдает от зависаний маршаллинга. Если ваш обмен с самописной базой или «Торговлей» регулярно доставляет проблемы, рассмотрите возможность публикации базы на веб-сервере и использования HTTPСоединение. Это сделает вашу систему более масштабируемой и устойчивой к обновлениям Windows.
Подводя итог: для устранения зависаний в текущем коде обязательно замените создание локальных структур на использование База1С.NewObject("Структура"). Это простое изменение в 90% случаев полностью решает проблему «мертвых» зависаний при обмене.