Как правильно закрыть OLE-соединение с базой 1С 7.7 и избежать ошибок при завершении работы

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

При интеграции современных систем на платформе 1С 8.x со старыми конфигурациями на 1С 7.7 через механизм OLE (Automation) программисты часто сталкиваются с неприятной проблемой. В момент программного закрытия соединения или завершения работы вызывающей обработки база 7.7 «падает» с ошибкой Runtime Error или просто зависает в списке процессов диспетчера задач. Рассмотрим подробнее, почему это происходит и как правильно организовать жизненный цикл OLE-объекта.

Разберем стандартный механизм инициализации и закрытия

Для начала проанализируем базовый код создания подключения. Обычно в 1С 8.x это выглядит следующим образом:


// Создание объекта
БазаОле = Новый COMОбъект("V77.Application");
ПутьКБазе = "C:\Bases\Salary77";
Пользователь = "Admin";
Пароль = "123";

// Формирование строки запуска
Параметры = "/D""" + ПутьКБазе + """ /N""" + Пользователь + """ /P""" + Пароль + """";
Результат = БазаОле.Initialize(БазаОле.RMTrade, Параметры, "NO_SPLASH_SHOW");

Если Результат = 0 Тогда
    Сообщить("Ошибка подключения!");
КонецЕсли;

Казалось бы, для закрытия соединения достаточно очистить переменную БазаОле, присвоив ей Неопределено или 0. Однако именно на этом этапе часто возникает краш системы. Выясним причину этой ситуации.

Выясним причину краша: влияние внешних компонент

Основная причина нестабильности при закрытии OLE-сессии заключается во внешних компонентах (ВК), загруженных в базе 7.7. В конфигурациях того времени активно использовались такие библиотеки, как FormEx.dll, 1cpp.dll или V7Plus.dll.

Когда база 7.7 открывается как OLE-сервер, у нее отсутствует полноценный графический интерфейс. Многие ВК при загрузке или при попытке штатного завершения работы пытаются обратиться к окнам 1С, перехватить события мыши или клавиатуры. Поскольку в режиме OLE этих объектов нет или они находятся в «замороженном» состоянии, обращение к памяти приводит к критической ошибке приложения.

Решение проблемы: необходимо предотвратить загрузку внешних компонент, если база запущена в режиме OLE.

Способ 1: Использование специального пользователя для OLE

Это самый простой и надежный метод. Мы создаем в базе 7.7 пользователя с именем, например, ОЛЕ. Далее в Глобальном модуле 7.7 в процедуре ПриНачалеРаботыСистемы() устанавливаем условие:


Процедура ПриНачалеРаботыСистемы()
    Если ИмяПользователя() <> "ОЛЕ" Тогда
        // Загружаем компоненты только для обычных пользователей
        ЗагрузитьВнешнююКомпоненту("FormEx.dll");
        ЗагрузитьВнешнююКомпоненту("V7Plus.dll");
    КонецЕсли;
КонецПроцедуры

Таким образом, при подключении извне под этим пользователем база останется «чистой» от лишнего кода, который конфликтует с OLE-режимом.

Способ 2: Использование параметров командной строки

Если создание отдельного пользователя нежелательно, проанализируем ситуацию с использованием ключа /C. При инициализации соединения мы можем передать в строку параметров произвольную метку:


СтрокаПодключения = "/D""C:\Base"" /N""Admin"" /CmodeOLE";
// Ключ /C позволяет передать строку, которую можно считать внутри 7.7

В самой базе 7.7 используем функцию КоманднаяСтрока() для проверки этого флага:


Если Найти(КоманднаяСтрока(), "modeOLE") = 0 Тогда
    // Если флаг не найден, значит это интерактивный вход
    // Можно загружать ВК
КонецЕсли;

Проанализируем правильный порядок уничтожения объектов в 1С 8.x

Часто процесс 1cv77.exe не закрывается (виснет в памяти), потому что в коде 1С 8.x остались «живые» ссылки на объекты из базы 7.7. Сборщик мусора 1С 8 не сможет уничтожить основной объект БазаОле, пока не будут уничтожены все зависимые объекты.

Рассмотрим пример неправильной очистки:


Выборка = БазаОле.CreateObject("Reference.Номенклатура");
Выборка.ВыбратьЭлементы();
// ... работа с данными
БазаОле = Неопределено; // ОШИБКА: Процесс может зависнуть, т.к. Выборка еще существует

Правильный алгоритм удаления ссылок:

  1. Сначала необходимо явно обнулить все переменные, которые ссылаются на справочники, документы, перечисления или запросы, созданные через БазаОле.CreateObject.
  2. Только после этого можно обнулять саму переменную БазаОле.
  3. Для надежности в некоторых случаях рекомендуется присваивать пустую строку: БазаОле = "";.

// Правильный порядок
Выборка = Неопределено;
Запрос = Неопределено;
Документ77 = Неопределено;
БазаОле = Неопределено;

Особенности выбора типа COM-сервера

При создании объекта мы использовали V77.Application. Однако стоит помнить, что существуют версии платформы, оптимизированные под разные лицензии. Если вы точно знаете тип используемой базы 7.7, лучше указывать конкретный программный идентификатор:

Явное указание версии иногда помогает избежать проблем с распределением лицензий и ускоряет инициализацию.

Проблема «невидимых» диалоговых окон

Если процесс 7.7 все же зависает, проанализируем Глобальный модуль базы 7.7 на наличие процедур ПриЗавершенииРаботыСистемы(). Если в ней прописаны вопросы пользователю (например, «Вы действительно хотите выйти?»), то в режиме OLE это окно будет невидимым, а процесс будет бесконечно ждать ответа, блокируя закрытие соединения.

Совет: Всегда оборачивайте интерактивные функции (Вопрос, Предупреждение, ОткрытьФорму) в условия, проверяющие режим работы. В 7.7 нет прямой функции ЭтоOLE(), поэтому вышеописанные методы с именем пользователя или параметром командной строки являются единственно верными инструментами для диагностики.

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

← На главную