В процессе разработки механизмов интеграции между различными конфигурациями 1С, например, при выгрузке данных из Зарплата и Управление Персоналом 3.1 в Зарплата и Управление Персоналом 2.5, программисты часто сталкиваются с необходимостью вызова методов внешних обработок. Одной из самых распространенных проблем в этой области является ошибка Метод объекта не обнаружен, возникающая даже в тех случаях, когда функция явно помечена как Экспорт в модуле объекта обработки.
В этой статье мы подробно разберем, почему возникает данная ситуация при использовании COMConnector, проанализируем различия между способами подключения и рассмотрим пошаговое решение проблемы.
Рассмотрим типичный сценарий: из основной базы создается COM-соединение с удаленной базой. Программист находит нужную внешнюю обработку в справочнике, выгружает её во временный файл и пытается создать объект через менеджер внешних обработок. Код выглядит примерно так:
Обр = Соединение.ВнешниеОбработки.Создать(ИмяФайла, Ложь);
Попытка
Знч = Обр.ВнешнееПодключение(Параметры);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Несмотря на то что метод ВнешнееПодключение существует и является экспортным, система выдает ошибку. Основная причина кроется в специфике работы технологии COMConnector. Рассмотрим подробнее, что происходит «под капотом».
COMConnector (V83.COMConnector) — это максимально «облегченный» вариант подключения. При его использовании в целевой базе создается сеанс типа «Внешнее соединение». В этом режиме не инициализируется пользовательский интерфейс, не доступны многие клиентские методы и, что самое важное, накладываются жесткие ограничения на доступ к контексту модулей. Если ваша внешняя обработка содержит обращения к глобальным переменным клиентского приложения или использует директивы компиляции, отличные от #НаСервере, COMConnector может просто «не увидеть» или не инициализировать модуль объекта должным образом.
Как показывает практика и обсуждение на форумах, наиболее быстрым и эффективным решением для старых конфигураций (таких как ЗУП 2.5) является использование V83.Application вместо V83.COMConnector.
V83.Application запускает полноценный экземпляр приложения (в режиме Automation-сервера). Несмотря на то что визуально окно программы может быть скрыто, внутри инициализируются все механизмы, доступные обычному пользователю, включая полные возможности встроенного языка для работы с объектами. Рассмотрим, как изменить код подключения:
// Вместо COMConnector используем Application
Соединитель = Новый COMОбъект("V83.Application");
ПараметрыПодключения = "Srvr=""sql02"";Ref=""test12"";Usr=""Админ"";Pwd=""password"";";
Попытка
// Метод Connect у Application инициализирует сеанс
Результат = Соединитель.Connect(ПараметрыПодключения);
Исключение
Сообщить("Не удалось подключиться: " + ОписаниеОшибки());
КонецПопытки;
После перевода кода на V83.Application, объект Обр, созданный через Соединение.ВнешниеОбработки.Создать(), начнет корректно отдавать свои экспортные методы. Это происходит потому, что контекст выполнения в режиме Application максимально приближен к работе в толстом клиенте, для которого и писалось большинство обработок в ЗУП 2.5.
Если по каким-то причинам (например, из-за требований к производительности или нехватки лицензий на полноценные сеансы) вы обязаны использовать COMConnector, следует изменить архитектуру вызова. Выясним причину: COMConnector отлично работает с методами общих модулей, у которых установлен флаг «Внешнее соединение».
Рассмотрим алгоритм действий:
Пример кода в общем модуле целевой базы:
Функция ВыполнитьДействиеВоВнешнейОбработке(ПутьКФайлу, Параметр1, Параметр2) Экспорт
// Внутри базы обработка создается в контексте сервера, а не COM-прослойки
ОбработкаОбъект = ВнешниеОбработки.Создать(ПутьКФайлу, Ложь);
Возврат ОбработкаОбъект.ВнешнееПодключение(Параметр1, Параметр2);
КонецФункции
Теперь из вызывающей базы (ЗУП 3.1) мы будем обращаться не к самой обработке напрямую, а к этому общему модулю:
// Пример вызова через COMConnector
Результат = Соединение.ИмяВашегоОбщегоМодуля.ВыполнитьДействиеВоВнешнейОбработке(ИмяФайла, ОргНаименование, Период);
Такой подход считается более надежным и «чистым» с точки зрения архитектуры 1С, так как он минимизирует передачу сложных объектов через границу COM-соединения.
Проанализируем еще один критический момент, который часто упускают при работе через COM. В исходном коде автора используется функция ПолучитьИмяВременногоФайла(). Здесь кроется потенциальная ловушка:
Расположение файла: Если код выполняется на стороне сервера 1С (в ЗУП 3.1), временный файл создается на диске сервера 1С под учетной записью службы (обычно USR1CV8). Когда вы передаете путь к этому файлу в Соединение.ВнешниеОбработки.Создать(ИмяФайла), база-приемник пытается найти этот файл на своем сервере.
Если базы расположены на разных физических серверах, вы получите ошибку Файл не обнаружен. Чтобы этого избежать, используйте следующие правила:
\\ServerShare\Exchange\Processing.epf).Обратим внимание на параметр БезопасныйРежим при создании обработки. В коде он установлен в Ложь:
Обр = Соединение.ВнешниеОбработки.Создать(ИмяФайла, Ложь);
Для интеграционных задач это оправдано. Если установить Истина, то внутри внешней обработки будут запрещены любые действия, которые могут нарушить безопасность системы: работа с файлами, выполнение COM-запросов, вызов привилегированных модулей. Поскольку интеграция часто требует записи файлов или обращения к метаданным, небезопасный режим является необходимым условием работы.
Если вы столкнулись с тем, что 1С не видит метод внешней обработки через COM, выполните следующие шаги:
V83.COMConnector на V83.Application. В 90% случаев для старых конфигураций это решает проблему мгновенно.&НаКлиенте или обращения к интерфейсным методам (Предупреждение, Вопрос), которые блокируют работу в режиме внешнего соединения.Используя эти рекомендации, вы сможете построить стабильную систему обмена данными между конфигурациями 1С разных поколений.