В процессе разработки на платформе 1С часто возникает задача хранить внешние обработки в базе данных (например, в специальном справочнике) и запускать их программно. Это удобно для централизованного обновления и управления дополнительным функционалом. Однако при попытке реализовать это в конфигурации на обычных формах, особенно без использования Библиотеки стандартных подсистем (БСП), можно столкнуться с неожиданными ошибками.
Давайте подробно разберем, почему стандартный, на первый взгляд, подход с использованием метода ВнешниеОбработки.Подключить() не работает с данными из хранилища и какой способ является правильным и надежным.
Рассмотрим типичный сценарий, с которым столкнулся автор вопроса на форуме. Идея была в том, чтобы получить двоичные данные обработки из реквизита справочника типа ХранилищеЗначения, поместить их во временное хранилище и передать полученный адрес в метод Подключить.
Посмотрим на пример кода, который приводит к ошибке:
// Находим нужную обработку в справочнике
ВО = Справочники.ВнешниеОбработки.НайтиПоНаименованию("МояОбработка");
// Получаем двоичные данные из хранилища
ДвоичныеДанные = ВО.ХранилищеВнешнейОбработки.Получить();
// Помещаем данные во временное хранилище и получаем адрес
АдресВоВременномХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанные);
// Пытаемся подключить обработку по адресу - ЭТОТ КОД ВЫЗОВЕТ ОШИБКУ!
ИмяОбработки = ВнешниеОбработки.Подключить(АдресВоВременномХранилище, , Ложь);
При выполнении последней строки система выдаст ошибку "Ошибка при вызове метода контекста "Подключить"". Выясним причину. Дело в том, что метод ВнешниеОбработки.Подключить() в качестве первого параметра ожидает не адрес данных в памяти (которым является адрес во временном хранилище), а полный путь к файлу на диске (например, "C:\Temp\my_processing.epf"). Платформа должна иметь возможность прочитать файл с диска для его регистрации в системе. Попытка передать ему что-то иное приводит к ошибке.
Наиболее надежный и универсальный способ для конфигураций на обычных формах — это эмуляция стандартного поведения, то есть временное сохранение обработки на диск. Алгоритм действий будет следующим:
.epf.Разберем этот процесс по шагам на основе рабочего примера кода.
Этот код является комплексным решением: он находит обработку, проверяет её вид, сохраняет во временный файл и открывает основную форму.
// 1. Находим нужный элемент справочника, где хранится обработка
ВнешняяОбработкаСсылка = Справочники.ВнешниеОбработки.НайтиПоНаименованию("Имя вашей обработки");
// 2. Проверяем, что это действительно обработка (а не, например, отчет)
// В вашей конфигурации перечисление и реквизит могут называться иначе
Если ВнешняяОбработкаСсылка.ВидОбработки = Перечисления.ВидыДополнительныхВнешнихОбработок.Обработка Тогда
// 3. Получаем имя для временного файла. Система сама подберет для него место
ИмяФайла = ПолучитьИмяВременногоФайла("epf");
// 4. Извлекаем двоичные данные из хранилища
ДвоичныеДанные = ВнешняяОбработкаСсылка.ХранилищеВнешнейОбработки.Получить();
// 5. Записываем данные в созданный временный файл
ДвоичныеДанные.Записать(ИмяФайла);
// 6. Получаем объект формы из файла и открываем его
// Имя формы можно не указывать, тогда откроется основная форма
Форма = ВнешниеОбработки.ПолучитьФорму(ИмяФайла);
Форма.Открыть();
// 7. (Необязательно, но рекомендуется) Удаляем временный файл после использования
// Этот шаг стоит выполнять, когда форма обработки будет закрыта,
// либо если дальнейшая работа с файлом не требуется.
// Для простоты примера, удаление показано сразу.
// В реальной задаче может потребоваться более сложная логика.
УдалитьФайлы(ИмяФайла);
КонецЕсли;
Этот метод абсолютно надежен и будет работать на любой версии платформы 1С, поддерживающей обычные формы.
Иногда требуется не открывать интерфейс обработки, а выполнить какую-либо её экспортную процедуру или функцию. Для этого используется связка методов Подключить() и Создать(). Алгоритм будет очень похож, но вместо открытия формы мы будем создавать объект обработки.
Рассмотрим на примере:
ИмяПодключеннойОбработки = "";
ИмяФайла = "";
Попытка
// Шаги 1-5: получение данных и сохранение во временный файл (аналогично предыдущему примеру)
ВнешняяОбработкаСсылка = Справочники.ВнешниеОбработки.НайтиПоНаименованию("ОбработкаСЭкспортнойПроцедурой");
ДвоичныеДанные = ВнешняяОбработкаСсылка.ХранилищеВнешнейОбработки.Получить();
ИмяФайла = ПолучитьИмяВременногоФайла("epf");
ДвоичныеДанные.Записать(ИмяФайла);
// Шаг 6: Подключаем обработку, используя путь к файлу.
// Метод возвращает уникальное имя, под которым обработка зарегистрирована в системе.
ИмяПодключеннойОбработки = ВнешниеОбработки.Подключить(ИмяФайла);
// Шаг 7: Создаем экземпляр объекта обработки
ОбъектОбработки = ВнешниеОбработки.Создать(ИмяПодключеннойОбработки);
// Шаг 8: Вызываем экспортный метод
ОбъектОбработки.МояЭкспортнаяПроцедура("Параметр1", 123);
// Получаем результат из экспортной функции
Результат = ОбъектОбработки.МояЭкспортнаяФункция();
Сообщить("Результат выполнения: " + Результат);
Исключение
Сообщить("Не удалось выполнить внешнюю обработку: " + ОписаниеОшибки());
КонецПопытки;
// Шаг 9: Отключаем обработку и удаляем временный файл
Если ЗначениеЗаполнено(ИмяПодключеннойОбработки) Тогда
ВнешниеОбработки.Отключить(ИмяПодключеннойОбработки);
КонецЕсли;
Если ЗначениеЗаполнено(ИмяФайла) Тогда
УдалитьФайлы(ИмяФайла);
КонецЕсли;
Важный момент: использование блока Попытка...Исключение и последующая обязательная очистка (отключение обработки и удаление файла) являются хорошей практикой. Это гарантирует, что даже в случае ошибки в коде обработки ваша система не останется с "мусором" в виде временных файлов и подключенных, но неиспользуемых обработок.
Таким образом, мы рассмотрели два надежных способа программной работы с внешними обработками, хранящимися в базе данных. Главный вывод — для взаимодействия с методами менеджера ВнешниеОбработки необходимо сначала материализовать двоичные данные в виде файла на диске.