Как в 1С 7.7 определить OLE-подключение при старте базы и вернуть результат?

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

При интеграции двух информационных баз 1С:Предприятия 7.7 через OLE-соединение часто возникает необходимость запускать специализированные алгоритмы исключительно в момент внешнего вызова, не затрагивая обычный интерактивный сеанс пользователей. Разберем особенности платформы 1С 7.7, проанализируем ограничения процедуры ПриНачалеРаботыСистемы() и рассмотрим надежные способы решения этой задачи.

Особенности и ограничения OLE-соединения в платформе 7.7

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

При этом возникают критические сложности:

  1. Штатных функций для определения типа запуска (интерактивный или OLE) в платформе 1С 7.7 нет.
  2. Любые интерактивные вызовы (такие как Предупреждение() или Вопрос()) приводят к мертвому зависанию скрытого OLE-процесса.
  3. Если вызвать команду СтатусВозврата(0) в процедуре ПриНачалеРаботыСистемы(), запуск системы прерывается немедленно. В вызывающей базе метод Initialize() возвращает 0, объект соединения не инициализируется до конца, и прочитать возвращаемые свойства напрямую через OLE становится невозможно.

Способ 1. Передача специального параметра через строку подключения (ВК FormEx)

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

Выясним причину работы данного метода: при вызове метода Initialize() мы передаем строку параметров подключения, куда можно дописать произвольный ключ, например /ThisIsAnOLEConnection.

Посмотрим на пример формирования строки подключения в базе «А»:


БазаОЛЕ = СоздатьОбъект("V77.Application");
КаталогБД = "C:\Bases\Base_EP";
ИмяПользователя = "РоботОЛЕ";
Пароль = "1601";

// Добавляем собственный ключ запуска в конец строки
СтрокаПодключения = "/d""" + КаталогБД + """ /n""" + ИмяПользователя + """ /p""" + Пароль + """ /ThisIsAnOLEConnection";

Если БазаОЛЕ.Initialize(БазаОЛЕ.RMTrade, СтрокаПодключения, "NO_SPLASH_SHOW") = 0 Тогда
    Предупреждение("Ошибка подключения к базе Б!");
КонецЕсли;

Теперь разберем, как принять и обработать этот ключ в базе «Б» внутри процедуры ПриНачалеРаботыСистемы() глобального модуля:


Процедура ПриНачалеРаботыСистемы()
    // Загружаем внешнюю компоненту для доступа к расширенным функциям
    Если ЗагрузитьВнешнююКомпоненту("formex.dll") = 1 Тогда
        Сервис = СоздатьОбъект("Сервис");
        СтрокаПараметров = Сервис.КоманднаяСтрока;
        
        Если Найти(СтрокаПараметров, "/ThisIsAnOLEConnection") > 0 Тогда
            // Выполняем алгоритм только для OLE-соединения
            РезультатАлгоритма = ВыполнитьСпециальныйАлгоритм();
            
            // Если нужно прервать запуск и передать строку:
            // записываем результат во временный файл обмена
            Если ПустаяСтрока(РезультатАлгоритма) = 0 Тогда
                ТекстФайл = СоздатьОбъект("Текст");
                ТекстФайл.ДобавитьСтроку(РезультатАлгоритма);
                ТекстФайл.Записать("C:\Bases\Exchange\result.txt");
                
                // Прерываем запуск базы "Б"
                СтатусВозврата(0);
                Возврат;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Способ 2. Проверка системной командной строки и состояния окна

Проанализируем ситуацию, когда требуется гарантированно отличить OLE-сеанс без передачи дополнительных параметров. Операционная система Windows при создании COM-объекта всегда запускает исполняемый файл платформы (1cv7.exe или 1cv7s.exe) со специальным системным ключом -Embedding (или /Automation).

С помощью внешних компонент или Windows API (функция GetCommandLine) можно проанализировать полную системную командную строку процесса. Наличие подстроки -Embedding со 100% точностью указывает на программный OLE-запуск.

Дополнительным признаком является видимость главного окна программы: при OLE-подключении окно запускается в скрытом режиме (свойство Visible = 0, а функция API IsWindowVisible возвращает ложь).

Способ 3. Штатный архитектурный подход: вызов функции после инициализации

Наиболее надежным и стабильным решением задачи возврата строки является отказ от выполнения логики внутри процедуры ПриНачалеРаботыСистемы(). Разберем по шагам, почему это эффективнее:

  1. Процедура ПриНачалеРаботыСистемы() в базе «Б» завершается в штатном режиме без ошибок.
  2. База «А» успешно получает рабочий OLE-объект.
  3. База «А» явно вызывает экспортную функцию базы «Б» через метод EvalExpr(), получает результат и сама корректно закрывает соединение.

Посмотрим на реализацию экспортируемой функции в глобальном модуле базы «Б»:


Функция глПолучитьДанныеДляБазыА() Экспорт
    Перем ТекстОтвета;
    
    // Выполняем нужный алгоритм
    ТекстОтвета = "Успешная обработка данных";
    
    Возврат ТекстОтвета;
КонецФункции

Посмотрим на код вызова в базе «А»:


БазаОЛЕ = СоздатьОбъект("V77.Application");
СтрокаПодключения = "/d""C:\Bases\Base_EP"" /n""РоботОЛЕ"" /p""1601""";

Если БазаОЛЕ.Initialize(БазаОЛЕ.RMTrade, СтрокаПодключения, "NO_SPLASH_SHOW") = 1 Тогда
    // Вызываем функцию и получаем строковый результат
    РезультатСтрока = БазаОЛЕ.EvalExpr("глПолучитьДанныеДляБазыА()");
    
    Если ПустаяСтрока(РезультатСтрока) = 0 Тогда
        Сообщить("Получен ответ от базы Б: " + РезультатСтрока);
    КонецЕсли;
    
    // Корректно завершаем сеанс базы "Б"
    БазаОЛЕ.ExecuteBatch("ЗавершитьРаботуСистемы(0)");
    БазаОЛЕ = 0;
Иначе
    Сообщить("Не удалось установить OLE-соединение");
КонецЕсли;

Корректное завершение OLE-сеанса и очистка ресурсов

Важно помнить: в 1С 7.7 обычного присвоения БазаОЛЕ = 0; часто недостаточно для выгрузки процесса. Исполняемый файл 1cv7s.exe может остаться висеть в диспетчере задач, блокируя каталог пользователя и файлы базы данных.

Для гарантированного освобождения памяти соблюдаем следующие правила:

  1. Перед закрытием вызываем принудительное завершение: БазаОЛЕ.ExecuteBatch("ЗавершитьРаботуСистемы(0)");.
  2. Обнуляем все переменные, которые ссылаются на внутренние объекты OLE-базы (справочники, документы, перечисления), и только в последнюю очередь обнуляем саму переменную подключения: БазаОЛЕ = 0;.
← На главную