В процессе сопровождения конфигурации 1С:Управление производственным предприятием 1.3 часто возникает необходимость автоматизировать выполнение определенных задач, которые реализованы в виде внешних обработок. Это удобно, так как позволяет обновлять логику без внесения изменений в основную конфигурацию и лишнего динамического обновления (или «выгона» пользователей). В данной статье мы подробно разберем, как организовать запуск такой обработки по расписанию, проанализируем возможные ошибки и рассмотрим лучшие практики написания кода для серверного контекста.
Предположим, у нас есть внешняя обработка (файл .epf), которая выполняет расчет себестоимости или формирование специфических отчетов. Нам нужно, чтобы эта обработка запускалась ежедневно в 2:00 ночи. В 1С:УПП 1.3, работающей на обычных формах, основным инструментом для этого является объект метаданных РегламентныеЗадания. Однако само регламентное задание может вызвать только процедуру из общего модуля. Следовательно, нам необходимо создать «прослойку», которая извлечет обработку из базы данных (если она там хранится) и запустит её выполнение.
Прежде всего, проанализируем модуль внешней обработки. Чтобы регламентное задание могло успешно вызвать процедуру, эта процедура должна быть объявлена в модуле объекта обработки с ключевым словом Экспорт.
Пример кода внутри модуля объекта внешней обработки:
Процедура ВыполнитьЗадание() Экспорт
// Логика вашей обработки
ЗаписьЖурналаРегистрации("РегламентноеЗадание.ВыполнениеОбработки",
УровеньЖурналаРегистрации.Информация, , , "Обработка успешно запущена");
// Здесь располагается основной код
КонецПроцедуры
Важно помнить, что в серверном контексте (где выполняется регламентное задание) отсутствуют такие объекты, как Предупреждение, Вопрос или любые другие элементы интерфейса. Поэтому убедитесь, что в коде обработки нет интерактивных действий.
Разберем последовательность действий в Конфигураторе:
ЗапускВнешнейОбработки).Рассмотрим основной программный код, который позволит нам «поднять» обработку из справочника ВнешниеОбработки и запустить её. Мы будем использовать метод записи двоичных данных во временный файл, так как это наиболее универсальный способ для старых версий платформы.
Проанализируем ситуацию: обработка хранится в стандартном справочнике. Нам нужно найти её по коду или наименованию, получить двоичные данные файла, сохранить их на диск сервера и создать объект обработки.
Процедура ЗапуститьОбработкуПоРасписанию() Экспорт
// Ищем обработку в справочнике
СсылкаНаОбработку = Справочники.ВнешниеОбработки.НайтиПоКоду("000000007");
Если СсылкаНаОбработку.Пустая() Тогда
ЗаписьЖурналаРегистрации("Ошибка.РегламентноеЗадание",
УровеньЖурналаРегистрации.Ошибка, , , "Внешняя обработка с кодом 000000007 не найдена!");
Возврат;
КонецЕсли;
// Получаем данные из хранилища
ДвоичныеДанные = СсылкаНаОбработку.ХранилищеВнешнейОбработки.Получить();
Если ДвоичныеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Генерируем уникальное имя временного файла
ИмяФайла = ПолучитьИмяВременногоФайла("epf");
Попытка
// Записываем данные на диск сервера
ДвоичныеДанные.Записать(ИмяФайла);
// Создаем объект обработки. Второй параметр "Ложь" отключает безопасный режим,
// что часто необходимо для записи данных в базу или файлы.
ВнешняяОбработкаОбъект = ВнешниеОбработки.Создать(ИмяФайла, Ложь);
// Вызываем экспортный метод
ВнешняяОбработкаОбъект.ВыполнитьЗадание();
Исключение
// Обязательно логируем ошибки
ЗаписьЖурналаРегистрации("Ошибка.РегламентноеЗадание",
УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
КонецПопытки;
// Очистка: удаляем временный файл, чтобы не засорять сервер
Попытка
УдалитьФайлы(ИмяФайла);
Исключение
// Игнорируем, если файл заблокирован, но в идеале логируем
КонецПопытки;
КонецПроцедуры
Вместо создания временного файла на диске, мы можем использовать метод ВнешниеОбработки.Подключить(). Этот способ считается более современным и «чистым», так как работа с файловой системой сводится к минимуму.
Рассмотрим пример:
// В серверном контексте
ИмяБиблиотеки = "МояОбработкаДляЗаданий";
ПутьКФайлу = ПолучитьИмяВременногоФайла("epf");
ДвоичныеДанные.Записать(ПутьКФайлу);
// Регистрируем обработку в памяти сервера
ВнешниеОбработки.Подключить(ПутьКФайлу, ИмяБиблиотеки, Ложь);
// Создаем объект по зарегистрированному имени
ОбработкаОбъект = ВнешниеОбработки.Создать(ИмяБиблиотеки);
ОбработкаОбъект.ВыполнитьЗадание();
Этот метод позволяет избежать некоторых проблем с правами доступа к временным папкам, хотя файл на диске всё равно временно создается для регистрации.
Выясним причину, по которой регламентное задание может не запускаться или выдавать ошибки:
ВнешниеОбработки.Создать() или Подключить() передать Истина в параметре безопасного режима, обработка не сможет работать с файлами, почтой или COM-объектами. Для большинства административных задач этот режим следует отключать (Ложь).1C:Enterprise 8.3 Server Agent (обычно это USR1CV8). У этого пользователя должны быть права на чтение и запись в папку временных файлов (Temp) на сервере.Экспорт, либо вы пытаетесь вызвать метод не у объекта обработки, а у чего-то другого. Всегда проверяйте, что ВнешниеОбработки.Создать() вернуло валидный объект.Поскольку регламентное задание работает в «фоне», мы не видим ошибок на экране. Проанализируем ситуацию: если задание завершилось с ошибкой, в консоли регламентных заданий мы увидим лишь краткое сообщение. Чтобы иметь полную картину, всегда используйте конструкцию Попытка...Исключение и записывайте подробности в Журнал регистрации.
Посмотрим на пример расширенного логирования:
ЗаписьЖурналаРегистрации("РегламентноеЗадание.Начало", УровеньЖурналаРегистрации.Информация);
НачалоВремени = ТекущаяДата();
// ... выполнение кода ...
КонецВремени = ТекущаяДата();
ЗаписьЖурналаРегистрации("РегламентноеЗадание.Конец",
УровеньЖурналаРегистрации.Информация, , ,
"Время выполнения: " + (КонецВремени - НачалоВремени) + " сек.");
Таким образом, мы создали надежный механизм запуска внешнего кода, который легко поддерживать и диагностировать. Использование справочника ВнешниеОбработки как хранилища позволяет централизованно управлять скриптами автоматизации во всей системе 1С:УПП 1.3.