В практике интеграции систем на платформе 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С).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% случаев полностью решает проблему «мертвых» зависаний при обмене.