К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как закрыть COM-соединение в 1С 8.3

Как корректно закрыть COM-соединение в 1С 8.3: обнуление объекта V83.COMConnector, завершение процессов dllhost и 1cv8, типичные ошибки и проверка результата.

COM-соединение в 1С 8.3 создаётся через объект V83.COMConnector (или V82.COMConnector для старых платформ) и позволяет одной базе подключаться к другой, а также внешним приложениям — обращаться к данным 1С. Проблема в том, что простое присвоение переменной значения Неопределено далеко не всегда освобождает ресурсы: сеанс в базе-источнике продолжает висеть, а процессы dllhost.exe и 1cv8.exe остаются в памяти.

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

Ниже разобраны рабочие способы закрытия соединения: штатное обнуление объектов, завершение процессов операционной системы, удаление сеансов через консоль кластера, а также типичные ошибки и способы проверки, что соединение действительно освобождено.

Как устроено COM-соединение и почему оно «зависает»

При создании COM-соединения фактически участвуют два объекта: сам коннектор V83.COMConnector и объект соединения, возвращаемый методом Connect(). Коннектор — это COM-компонент, зарегистрированный в операционной системе, а соединение — отдельный экземпляр, внутри которого запускается полноценный сеанс работы с информационной базой.

Для файловой базы подключение выполняется через строку вида File="C:\Bases\Trade";Usr="Администратор";Pwd="123", для клиент-серверной — через Srvr="Server1";Ref="Trade";Usr="...";Pwd="...". В обоих случаях на стороне базы-источника создаётся полноценный сеанс, который занимает лицензию и виден в консоли кластера или в списке активных пользователей.

«Зависание» происходит по простой причине: COM-объекты живут по правилам подсчёта ссылок Windows, а не по правилам сборки мусора 1С. Пока существует хотя бы одна живая ссылка на объект соединения — в переменной, в реквизите формы, в глобальном контексте, в кэше внешней обработки — сеанс не завершится, даже если код, создававший соединение, давно отработал.

Штатное закрытие соединения в коде 1С

Основной и самый надёжный способ — явно обнулить оба объекта в том же коде, где они создавались. Порядок важен: сначала освобождается соединение, затем коннектор. Обратный порядок может оставить «осиротевший» сеанс.

// Создание соединения

Коннектор = Новый COMОбъект("V83.COMConnector");

Соединение = Коннектор.Connect("File=""C:\Bases\Trade"";Usr=""Админ"";Pwd=""123""");

// ... работа с данными ...

// Закрытие: сначала соединение, потом коннектор

Соединение = Неопределено;

Коннектор = Неопределено;

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

Отдельный случай — соединение, хранящееся в реквизите формы или в глобальной переменной модуля для повторного использования. Такой подход допустим, но тогда закрывать его нужно в обработчике закрытия формы (ПриЗакрытии) или при завершении работы сеанса, иначе сеанс в базе-источнике проживёт столько же, сколько открыта форма.

Порядок корректного закрытия в коде
  1. 1
    Завершите все операции чтения и записи через соединение
  2. 2
    Присвойте переменной соединения значение Неопределено
  3. 3
    Присвойте переменной коннектора значение Неопределено
  4. 4
    Продублируйте обнуление в ветке Исключение блока Попытка
  5. 5
    Проверьте в консоли кластера, что сеанс исчез из списка активных

Завершение процессов операционной системы

Когда код уже отработал, а сеанс остался, помогает завершение процессов на стороне того компьютера, где создавалось COM-соединение. Для файловой базы и толстого клиента это обычно процесс 1cv8.exe или 1cv8c.exe вызывающего приложения. Если соединение создавалось из внешнего приложения (скрипта, Excel, сторонней программы), COM-объект может размещаться в суррогатном процессе dllhost.exe.

Завершить процесс можно через Диспетчер задач (вкладка «Подробности» → найти процесс → «Снять задачу») или командой taskkill. Важно понимать, чей это процесс: завершение чужого 1cv8.exe оборвёт работу пользователя без сохранения данных.

cmd
taskkill /F /IM dllhost.exe

Команда taskkill /F /IM dllhost.exe завершит все суррогатные процессы COM+, включая те, что могут использоваться другими приложениями. Более точечный вариант — найти конкретный PID через Диспетчер задач и завершить его: taskkill /F /PID 12345. После завершения процесса сеанс в клиент-серверной базе исчезнет не мгновенно: кластер удалит его по таймауту, обычно в течение нескольких минут.

Удаление сеанса через консоль кластера

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

Выделите сеанс и выберите в контекстном меню «Удалить». Сеанс завершится немедленно, соединение на стороне вызывающего кода станет нерабочим — при следующем обращении к нему возникнет ошибка. Это нормально, если вызовы уже завершены.

Дополнительно стоит проверить ветку «Соединения» той же консоли: там видно, какой рабочий процесс кластера обслуживает соединение. Если зависших сеансов много и они регулярно появляются от одного и того же регламентного задания или обработки — проблему нужно решать в коде, а не ручной чисткой.

Профилактика: как не допускать зависших соединений

Самая частая причина зависаний — архитектура «создал соединение и забыл». Несколько практических мер заметно снижают число таких ситуаций. Во-первых, создавайте соединение как можно ближе к месту использования и закрывайте в том же методе — это локализует время жизни объекта. Во-вторых, всегда оборачивайте работу с соединением в Попытка/Исключение с обнулением в обеих ветках.

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

Сравнение вариантов закрытия

Обнуление объектов в коде

Штатный и безопасный способ. Подходит всегда, когда есть доступ к коду. Ограничение: не работает, если ссылка на объект потеряна или код завершился аварийно.

Завершение процесса ОС

Помогает при зависшем клиенте или внешнем приложении. Риск: обрывает все соединения процесса, данные не сохраняются.

Удаление сеанса в консоли кластера

Точечное завершение со стороны сервера. Требует прав администратора кластера и доступно только в клиент-серверном режиме.

Типичные ошибки при закрытии COM-соединения

Ошибки в этой теме повторяются из проекта в проект. Самая распространённая — обнуление только соединения при живом коннекторе или наоборот: оба объекта должны быть освобождены. Вторая частая ошибка — хранение соединения в реквизите формы без закрытия в ПриЗакрытии: форма закрылась, а сеанс в базе-источнике остался.

Третья ошибка — попытка «переиспользовать» соединение после того, как оно было разорвано сервером по таймауту. Такой объект выглядит живым, но любое обращение к нему вызывает исключение. Правильный подход — пересоздавать соединение заново. Четвёртая ошибка — создание соединения на сервере 1С в фоновом задании без учёта того, что COM-компонент должен быть зарегистрирован именно на сервере, а не на клиентской машине разработчика.

Типичные ошибки
01
Обнуление только одного объекта: соединения без коннектора или наоборот — сеанс может не освободиться
02
Хранение соединения в реквизите формы без закрытия в ПриЗакрытии — сеанс живёт, пока открыта форма
03
Отсутствие обнуления в ветке Исключение — при ошибке соединение остаётся висеть
04
Повторное использование соединения после таймаута сервера — обращение вызывает исключение вместо переподключения
05
Завершение чужого процесса 1cv8.exe вместо своего — обрыв работы пользователя без сохранения

Как проверить, что соединение действительно закрыто

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

Для файловой базы проверка проще: файл 1Cv8.1CL (журнал сеансов) и наличие лишних процессов 1cv8.exe в Диспетчере задач. Если после закрытия своего приложения лишний процесс 1С остался — соединение не было освобождено корректно. Дополнительный признак успеха — возможность открыть базу монопольно: зависший COM-сеанс блокирует установку монопольного режима так же, как обычный пользовательский сеанс.

Контрольные точки

Как проверить результат

Список сеансов в консоли кластера
Норма

Сеанс с приложением «COM-соединение» отсутствует

Тревожный признак

Сеанс висит спустя несколько минут после закрытия

Процессы на клиентской машине
Норма

Лишних процессов 1cv8.exe и dllhost.exe нет

Тревожный признак

Процесс остался после завершения приложения

Монопольный доступ к базе
Норма

Монопольный режим устанавливается без ошибок

Тревожный признак

Ошибка «база используется другими сеансами»

Итог

Что важно запомнить

COM-соединение закрывается явным обнулением обоих объектов — соединения и коннектора — желательно в блоке Попытка/Исключение. Если сеанс завис, его завершают через Диспетчер задач или консоль кластера. Результат проверяют по списку сеансов и возможности монопольного доступа.

Частые вопросы о закрытии COM-соединений

Достаточно ли присвоить соединению Неопределено, чтобы сеанс закрылся?

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

Почему сеанс в консоли кластера не исчезает сразу после закрытия?

Кластер серверов 1С удаляет оборванные сеансы не мгновенно, а по внутреннему таймауту — обычно в течение нескольких минут. Если сеанс висит существенно дольше, значит соединение на клиентской стороне не было освобождено.

Чем завершение сеанса в консоли кластера отличается от завершения процесса?

Удаление сеанса в консоли — точечное действие на стороне сервера: обрывается только выбранный сеанс, клиентский процесс при этом продолжает работать. Завершение процесса на клиенте убивает всё приложение целиком, включая несохранённые данные.

Можно ли закрыть COM-соединение из кода базы-источника?

Напрямую из кода базы-источника закрыть чужое COM-соединение нельзя — оно управляется вызывающей стороной. Административный вариант — завершить сеанс через программный интерфейс администрирования кластера (COM-объект V83.ComAdmin или агент сервера).

Что делать, если COM-соединения зависают регулярно?

Регулярные зависания указывают на ошибку в коде: соединение не обнуляется при исключениях или хранится в долгоживущих объектах. Найдите место создания соединения, добавьте обнуление в обе ветки Попытка/Исключение. Если обмен регулярный — рассмотрите переход на HTTP-сервисы вместо COM.

Занимает ли зависший COM-сеанс лицензию 1С?

Да. COM-соединение создаёт полноценный сеанс, который расходует клиентскую лицензию наравне с обычным пользовательским сеансом. Массовые зависшие соединения могут исчерпать лицензии и заблокировать вход пользователей.