При разработке и сопровождении конфигураций на платформе 1С:Предприятие 8.3 часто возникает задача динамического подключения функционала. Например, нам необходимо открыть внешнюю обработку (файл с расширением .epf) или отчет (.erf), который находится на диске или в сетевой папке, но при этом мы не хотим или не можем добавить этот файл в состав метаданных конфигурации (в справочник "Дополнительные отчеты и обработки").
Простое использование метода ОткрытьФорму с указанием пути к файлу в управляемом приложении не сработает так, как это было в обычных формах (версии 8.1 или 8.2). В клиент-серверной архитектуре и интерфейсе "Такси" требуется иной подход, связанный с временным подключением обработки к сеансу. Разберем подробно, как реализовать этот механизм правильно, безопасно и эффективно.
Прежде чем писать код, давайте проанализируем, как платформа работает с внешними файлами. В управляемом приложении код исполняется раздельно на клиенте и на сервере. Файл обработки физически может находиться на машине клиента, но создать объект обработки (для вызова его экспортных методов) или получить структуру его формы платформа должна, имея доступ к этому объекту в контексте сервера или через механизм безопасного хранилища.
Для решения задачи мы будем использовать менеджер ВнешниеОбработки (или ВнешниеОтчеты) и его метод Подключить. Этот метод регистрирует файл в системе на время сеанса и возвращает нам специальное "внутреннее" имя, которое мы и будем использовать для открытия формы.
Разделим задачу на несколько логических этапов, которые мы должны выполнить в нашем коде:
Рассмотрим ситуацию, когда файл обработки лежит в доступной для сервера папке (например, локальный диск сервера или сетевая шара). В этом случае процедура будет выглядеть следующим образом.
Создадим функцию на сервере, которая будет отвечать за регистрацию обработки:
&НаСервере
Функция ПодключитьВнешнююОбработкуНаСервере(ПолноеИмяФайла)
// Подключаем обработку.
// Параметр Ложь означает, что мы НЕ используем безопасный режим (если доверяем источнику).
// Если файл из ненадежного источника, лучше передать Истина.
ИмяОбработки = ВнешниеОбработки.Подключить(ПолноеИмяФайла, , Ложь);
// Возвращаем внутреннее имя, которое присвоила платформа
Возврат ИмяОбработки;
КонецФункции
Теперь рассмотрим код на клиенте, который вызывает эту функцию и открывает форму:
&НаКлиенте
Процедура ОткрытьОбработку(Команда)
ПутьКФайлу = "C:\Exchange\MyProcessor.epf"; // Путь на диске СЕРВЕРА
ИмяОбработки = ПодключитьВнешнююОбработкуНаСервере(ПутьКФайлу);
// Формируем ключ уникальности, чтобы не плодить окна, если обработка уже открыта
КлючУникальности = "ВнешняяОбработка_" + ИмяОбработки;
// Открываем основную форму обработки
// Строка вида "ВнешняяОбработка.ИмяГенерируемоеПлатформой.Форма"
ОткрытьФорму("ВнешняяОбработка." + ИмяОбработки + ".Форма", , , КлючУникальности);
КонецПроцедуры
Давайте проанализируем более распространенный случай: пользователь выбирает файл на своем компьютере через диалог выбора файла, и мы должны открыть этот файл. Здесь добавляется шаг передачи данных через ПоместитьВоВременноеХранилище.
Разберем полный цикл действий:
&НаКлиенте
Процедура ЗагрузитьИОткрытьОбработку(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Внешние обработки (*.epf)|*.epf|Внешние отчеты (*.erf)|*.erf";
Если Не Диалог.Выбрать() Тогда
Возврат;
КонецЕсли;
Попытка
// 1. Помещаем файл во временное хранилище
// Используем УникальныйИдентификатор формы, чтобы хранилище жило пока жива форма
АдресВХранилище = "";
ПоместитьФайл(АдресВХранилище, Диалог.ПолноеИмяФайла, , Ложь);
// 2. Подключаем обработку на сервере и получаем имя
ПодключенноеИмя = ПодключитьОбработкуПоАдресу(АдресВХранилище);
// 3. Открываем форму
// Обратите внимание: для отчетов используем "ВнешнийОтчет.", для обработок "ВнешняяОбработка."
// Здесь для примера считаем, что это обработка
ПутьКФорме = "ВнешняяОбработка." + ПодключенноеИмя + ".Форма";
ОткрытьФорму(ПутьКФорме);
Исключение
Сообщить("Не удалось открыть файл: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
&НаСервере
Функция ПодключитьОбработкуПоАдресу(АдресВХранилище)
// Метод Подключить умеет работать не только с путем к файлу, но и с адресом во временном хранилище
// Это позволяет не сохранять файл физически на диск сервера
Возврат ВнешниеОбработки.Подключить(АдресВХранилище, , Ложь);
КонецФункции
Часто нам нужно не просто открыть форму, но и передать в неё какие-то данные (например, ссылку на объект, дату или настройки). Рассмотрим, как это сделать, используя структуру параметров метода ОткрытьФорму.
В коде открытия на клиенте добавим создание структуры:
&НаКлиенте
Процедура ОткрытьСПараметрами(ИмяПодключеннойОбработки)
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ДатаНачала", НачалоДня(ТекущаяДата()));
ПараметрыФормы.Вставить("Организация", Объект.Организация);
ПутьКФорме = "ВнешняяОбработка." + ИмяПодключеннойОбработки + ".Форма";
// Передаем структуру вторым параметром
ОткрытьФорму(ПутьКФорме, ПараметрыФормы);
КонецПроцедуры
Важное замечание: Чтобы принимающая внешняя обработка "увидела" эти параметры, в модуле её формы в процедуре ПриСозданииНаСервере необходимо обработать коллекцию Параметры.
Давайте подробно обсудим параметр "БезопасныйРежим" в методе Подключить. В примерах выше мы использовали значение Ложь. Это означает, что подключаемый код будет выполняться без ограничений: он сможет читать любые файлы на сервере, обращаться к интернету, использовать COM-объекты.
Если мы укажем Истина (или опустим параметр, так как Истина — это значение по умолчанию в некоторых версиях БСП, но в платформенном методе важно контролировать это явно), то на обработку накладываются ограничения:
Если ваша внешняя обработка должна выполнять "опасные" действия (например, загрузку данных из Excel через COM или обмен с сайтом), обязательно указывайте Ложь в третьем параметре метода Подключить. Иначе вы получите ошибку нарушения прав доступа при выполнении кода обработки.
Иногда во внешней обработке создано несколько форм, и нам нужно открыть не основную, а конкретную (например, форму настроек). Проанализируем, как сформировать путь в этом случае.
Имя, возвращаемое функцией Подключить, является идентификатором объекта в сеансе. Стандартный путь выглядит так: ВнешняяОбработка.Имя.Форма. Это открывает основную форму.
Если нужно открыть форму с именем ФормаНастройки, строковый путь должен быть таким:
Путь = "ВнешняяОбработка." + ПодключенноеИмя + ".Форма.ФормаНастройки";
Обратите внимание на двойное использование слова "Форма". Первое указывает на коллекцию форм, второе — это имя метаданных конкретной формы внутри файла обработки.
При реализации данного механизма мы можем столкнуться с рядом типовых проблем. Давайте разберем их причины:
Убедитесь, что код выполняется в правильном контексте. Если вы передаете путь C:\Users\Admin\... с клиента на сервер, сервер будет искать этот путь у себя, а не на компьютере пользователя. Используйте временное хранилище для передачи файлов.
Как обсуждалось выше, проверьте третий параметр метода ВнешниеОбработки.Подключить. Установите его в Ложь, если обработке требуются расширенные права.
Убедитесь, что этот код выполняется на сервере. Менеджеры ВнешниеОбработки и ВнешниеОтчеты недоступны на тонком клиенте напрямую.
Используя приведенные выше подходы, вы сможете гибко управлять подключением внешнего функционала в ваших решениях на 1С 8.3, сохраняя архитектуру приложения чистой и не загромождая дерево конфигурации редко используемыми утилитами.