При интеграции современных систем на платформе 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.
Это самый простой и надежный метод. Мы создаем в базе 7.7 пользователя с именем, например, ОЛЕ. Далее в Глобальном модуле 7.7 в процедуре ПриНачалеРаботыСистемы() устанавливаем условие:
Процедура ПриНачалеРаботыСистемы()
Если ИмяПользователя() <> "ОЛЕ" Тогда
// Загружаем компоненты только для обычных пользователей
ЗагрузитьВнешнююКомпоненту("FormEx.dll");
ЗагрузитьВнешнююКомпоненту("V7Plus.dll");
КонецЕсли;
КонецПроцедуры
Таким образом, при подключении извне под этим пользователем база останется «чистой» от лишнего кода, который конфликтует с OLE-режимом.
Если создание отдельного пользователя нежелательно, проанализируем ситуацию с использованием ключа /C. При инициализации соединения мы можем передать в строку параметров произвольную метку:
СтрокаПодключения = "/D""C:\Base"" /N""Admin"" /CmodeOLE";
// Ключ /C позволяет передать строку, которую можно считать внутри 7.7
В самой базе 7.7 используем функцию КоманднаяСтрока() для проверки этого флага:
Если Найти(КоманднаяСтрока(), "modeOLE") = 0 Тогда
// Если флаг не найден, значит это интерактивный вход
// Можно загружать ВК
КонецЕсли;
Часто процесс 1cv77.exe не закрывается (виснет в памяти), потому что в коде 1С 8.x остались «живые» ссылки на объекты из базы 7.7. Сборщик мусора 1С 8 не сможет уничтожить основной объект БазаОле, пока не будут уничтожены все зависимые объекты.
Рассмотрим пример неправильной очистки:
Выборка = БазаОле.CreateObject("Reference.Номенклатура");
Выборка.ВыбратьЭлементы();
// ... работа с данными
БазаОле = Неопределено; // ОШИБКА: Процесс может зависнуть, т.к. Выборка еще существует
Правильный алгоритм удаления ссылок:
БазаОле.CreateObject.БазаОле.БазаОле = "";.
// Правильный порядок
Выборка = Неопределено;
Запрос = Неопределено;
Документ77 = Неопределено;
БазаОле = Неопределено;
При создании объекта мы использовали V77.Application. Однако стоит помнить, что существуют версии платформы, оптимизированные под разные лицензии. Если вы точно знаете тип используемой базы 7.7, лучше указывать конкретный программный идентификатор:
V77.Application — будет запущен последний зарегистрированный в реестре сервер (общий случай).V77S.Application — SQL-версия.V77M.Application — сетевая версия.V77L.Application — локальная версия.Явное указание версии иногда помогает избежать проблем с распределением лицензий и ускоряет инициализацию.
Если процесс 7.7 все же зависает, проанализируем Глобальный модуль базы 7.7 на наличие процедур ПриЗавершенииРаботыСистемы(). Если в ней прописаны вопросы пользователю (например, «Вы действительно хотите выйти?»), то в режиме OLE это окно будет невидимым, а процесс будет бесконечно ждать ответа, блокируя закрытие соединения.
Совет: Всегда оборачивайте интерактивные функции (Вопрос, Предупреждение, ОткрытьФорму) в условия, проверяющие режим работы. В 7.7 нет прямой функции ЭтоOLE(), поэтому вышеописанные методы с именем пользователя или параметром командной строки являются единственно верными инструментами для диагностики.
Соблюдение этих правил позволит вам создавать стабильные интеграционные решения, которые не требуют ручного вмешательства в диспетчер задач после каждого обмена данными.