В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача динамического запуска внешних обработок. Это особенно актуально, когда логика бизнес-процессов хранится не в файловой системе, а непосредственно в базе данных (например, в справочнике или константе в виде бинарных данных). Такой подход позволяет централизованно обновлять инструменты для всех пользователей без необходимости копирования файлов по папкам.
В данной статье мы подробно разберем, как извлечь обработку из хранилища, подключить ее к сеансу, инициализировать форму и выполнить программный код, расположенный внутри этой формы. Мы проанализируем не только базовый механизм, но и важные нюансы безопасности и оптимизации.
Рассмотрим ситуацию, когда файл .epf загружен в реквизит с типом ХранилищеЗначения. Для того чтобы платформа смогла с ним работать, нам необходимо пройти через несколько этапов: получение двоичных данных, создание временного файла, регистрация обработки в системе и, наконец, обращение к ее контексту.
Разберем реализацию этой задачи на примере кода, предоставленного в сообществе. Процесс разделен на клиентскую и серверную части, что критически важно для управляемого приложения.
&НаКлиенте
Процедура ВыполнитьДействиеВыполнитьОбработкуНаКлиентеНаФорме()
ПараметрыВыполнения = Новый Структура;
// 1. Получаем двоичные данные обработки из базы на сервер
ДвДанныеВоВременномХранилище = "";
ИмяВнешнейОбработки(ДвДанныеВоВременномХранилище);
// 2. Извлекаем данные из хранилища и записываем во временный файл на клиенте
ДвДанные = ПолучитьИзВременногоХранилища(ДвДанныеВоВременномХранилище);
ИмяФайла = ПолучитьИмяВременногоФайла(".epf");
ДвДанные.Записать(ИмяФайла);
// 3. Помещаем файл обратно на сервер для регистрации в менеджере внешних обработок
АдресХранилища = "";
Результат = ПоместитьФайл(АдресХранилища, ИмяФайла, , Ложь);
// 4. Подключаем обработку на сервере
ИмяОбработки = ПодключитьВнешнююОбработку(АдресХранилища);
// 5. Получаем форму и вызываем экспортную процедуру
ФормаОбработки = ПолучитьФорму("ВнешняяОбработка." + ИмяОбработки + ".Форма");
Попытка
ФормаОбработки.ЭкспортнаяПроцедураНаФорме(ПараметрыВыполнения);
Исключение
Сообщить("Не удалось вызвать процедуру формы: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
&НаСервере
Процедура ИмяВнешнейОбработки(ДвДанныеВоВременномХранилище)
// Предположим, обработка хранится в справочнике
ОбработкаСсылка = Справочники.ДополнительныеОбработки.НайтиПоНаименованию("МояОбработка");
ДвДанные = ОбработкаСсылка.ХранилищеОбработки.Получить();
ДвДанныеВоВременномХранилище = ПоместитьВоВременноеХранилище(ДвДанные, Новый УникальныйИдентификатор);
КонецПроцедуры
&НаСервере
Функция ПодключитьВнешнююОбработку(АдресХранилища)
// Используем менеджер ВнешниеОбработки для регистрации файла в сеансе
Возврат ВнешниеОбработки.Подключить(АдресХранилища);
КонецФункции
Давайте проанализируем, что происходит в каждом блоке кода. Процесс начинается с вызова процедуры ИмяВнешнейОбработки на сервере. Здесь мы обращаемся к базе данных, извлекаем объект ДвоичныеДанные из реквизита и помещаем его во временное хранилище сеанса. Это необходимо, так как напрямую передать большой объем двоичных данных между сервером и клиентом лучше всего через Адрес в хранилище.
Затем на стороне клиента мы используем ПолучитьИмяВременногоФайла(".epf"). Это важный шаг: платформа создает уникальный путь в локальной временной директории пользователя. Запись данных методом ДвДанные.Записать(ИмяФайла) фактически воссоздает файл обработки на диске клиента.
Следующий этап — использование метода ВнешниеОбработки.Подключить(). Обратите внимание, что этот метод возвращает внутреннее имя, под которым обработка зарегистрирована в текущем сеансе. Мы не можем просто использовать имя файла, так как платформа присваивает обработке уникальный идентификатор (например, "ВнешняяОбработка1"), чтобы избежать конфликтов имен, если подключено несколько разных файлов.
Функция ПолучитьФорму() позволяет нам инициализировать объект формы внешней обработки. В строке кода ПолучитьФорму("ВнешняяОбработка." + ИмяОбработки + ".Форма") крайне важно правильно сконструировать строку пути. После этого мы получаем доступ к контексту формы. Важное условие: вызываемая процедура ЭкспортнаяПроцедураНаФорме обязательно должна иметь ключевое слово Экспорт в модуле управляемой формы.
Рассмотрим, почему иногда этот подход может не сработать или быть избыточным. Если ваша задача — просто выполнить расчеты на сервере без визуального отображения окна пользователю, получение формы является "дорогой" операцией с точки зрения ресурсов. В таких случаях эффективнее работать с объектом обработки.
Проанализируем ситуацию, когда нам нужно выполнить серверный код обработки. Вместо создания формы мы можем создать экземпляр объекта обработки на сервере. Для этого экспортная процедура должна быть размещена в Модуле объекта обработки.
&НаСервере
Процедура ВыполнитьЛогикуНаСервере(АдресХранилища)
ИмяОбработки = ВнешниеОбработки.Подключить(АдресХранилища);
ОбъектОбработки = ВнешниеОбработки.Создать(ИмяОбработки);
// Вызов процедуры из Модуля объекта
ОбъектОбработки.ВыполнитьДействиеСерверное();
КонецПроцедуры
Этот способ предпочтительнее для фоновых заданий, регламентных операций или сложных расчетов, так как он не требует инициализации интерфейсных элементов и передачи данных на клиентскую сторону для отрисовки формы.
При использовании метода ВнешниеОбработки.Подключить() следует помнить о безопасности. По умолчанию внешние обработки могут иметь доступ к файловой системе, реестру и внешним ресурсам. Выясним, как управлять правами доступа при подключении:
Подключить передать Истина, обработка будет запущена с ограничениями. Она не сможет выполнять потенциально опасные операции.Разберем типичную ошибку начинающих разработчиков — накопление временных файлов. Хотя платформа старается очищать папку временных файлов при завершении сеанса, при интенсивной работе (например, если обработка запускается сотни раз в день) место на диске может закончиться быстрее, чем закроется сеанс пользователя.
Рекомендуем всегда использовать блок Попытка...КонецПопытки и явно удалять временный файл после его использования:
ИмяФайла = ПолучитьИмяВременногоФайла(".epf");
Попытка
// Логика работы с файлом
// ...
Исключение
ЗаписатьЛогСобытий(ОписаниеОшибки());
КонецПопытки;
// Очистка
УдалитьФайлы(ИмяФайла);
Если вы работаете в современной типовой конфигурации (например, 1С:ERP, УТ 11 или БП 3.0), рассмотрим более правильный архитектурный путь. В БСП существует подсистема "Дополнительные отчеты и обработки". Для удобного переноса и обновления таких элементов подойдёт инструмент для массового экспорта и импорта дополнительных отчетов и обработок.
Вместо ручного написания кода по сохранению файлов, лучше зарегистрировать вашу обработку в справочнике ДополнительныеОтчетыИОбработки. Программный интерфейс БСП (модуль ДополнительныеОтчетыИОбработкиКлиент и ДополнительныеОтчетыИОбработкиСервер) предоставляет готовые методы для запуска таких обработок, которые уже учитывают права доступа, ведение журнала регистрации и корректную работу в веб-клиенте. Для быстрой разработки таких модулей можно использовать шаблон дополнительной обработки на основе БСП с системой хранения настроек.
Итог: Предложенный метод с ручным созданием временного файла и использованием ПолучитьФорму является универсальным и подходит для любых конфигураций на платформе 8.3. Однако всегда стоит оценивать, где именно должен выполняться код — на клиенте в контексте формы или на сервере в контексте объекта — и не забывать об удалении временных данных после завершения работы.