При работе с платформой 1С:Предприятие 8.3 в серверном варианте мы часто сталкиваемся с необходимостью автоматизировать различные задачи, используя внешние обработки. Однако попытка запуска внешней обработки (особенно если она не подписана или является "небезопасной") напрямую из регламентного задания часто приводит к ошибке, связанной с ограничениями безопасности на сервере 1С. В данной статье мы подробно разберем, почему возникает такая проблема, и рассмотрим проверенное решение с примерами кода.
Сервер 1С:Предприятия работает в режиме повышенной безопасности. Это означает, что он по умолчанию не разрешает прямое выполнение произвольного кода из внешних файлов, таких как .epf или .erf. Целью такого ограничения является предотвращение потенциально вредоносных действий, которые могли бы быть вызваны непроверенным кодом. Если мы пытаемся запустить такую обработку через регламентное задание, которое выполняется на сервере, система блокирует ее выполнение, выдавая ошибку.
Даже если мы попытаемся использовать стандартные механизмы операционной системы, такие как ЗапуститьПриложение() или вызов командной строки через WScript.Shell, это также будет заблокировано на сервере, поскольку эти действия считаются небезопасными для серверного контекста.
Для "небезопасных" обработок (тех, которые имеют потенциальный доступ к файловой системе, сетевым ресурсам или могут выполнять произвольные действия, не контролируемые платформой 1С) особенно важен строгий контроль. Система 1С не доверяет таким файлам без явного разрешения или использования специальных механизмов.
Для выполнения внешних обработок на сервере платформа 1С предоставляет специальный механизм – справочник ДополнительныеОтчетыИОбработки. Этот справочник является своего рода "песочницей" или "доверенным контейнером" для внешнего кода. Когда мы добавляем обработку в этот справочник, 1С регистрирует ее внутри своей конфигурации и может контролировать ее выполнение, в том числе снимать ограничения безопасности для конкретного элемента, если это необходимо.
При использовании этого механизма, вместо прямого запуска файла, мы:
ДополнительныеОтчетыИОбработки.Такой подход позволяет нам обойти серверные ограничения безопасности, поскольку выполнение происходит уже из доверенного контекста, который контролируется самой системой 1С.
Давайте рассмотрим подробный алгоритм действий, который позволит нам программно запустить внешнюю небезопасную обработку на сервере 1С с помощью регламентного задания. Мы будем использовать пример, в котором загружаем прайс-лист.
Прежде чем мы начнем работать с обработкой, нам необходимо определить путь к файлу и убедиться, что файл существует. Это базовая проверка, которая поможет избежать ошибок на ранней стадии.
Создадим процедуру на сервере, которая будет выполнять всю логику.
&НаСервере
Процедура ВыполнитьВнешнююОбработкуНаСервере()
// Определяем путь к файлу внешней обработки на сервере.
// Важно: этот путь должен быть доступен для сервера 1С.
ПутьКФайлуОбработки = "C:\МоиОбработки\ЗагрузкаПрайса.epf";
// Проверяем существование файла. Если файл не найден, сообщаем об этом и завершаем работу.
Если Не ФайлСуществует(ПутьКФайлуОбработки) Тогда
Сообщить("Файл обработки не найден: " + ПутьКФайлуОбработки, СтатусСообщения.Важное);
Возврат;
КонецЕсли;
На этом шаге мы программно создадим новый элемент в справочнике ДополнительныеОтчетыИОбработки и заполним его необходимыми данными, включая саму внешнюю обработку и флаг, отключающий безопасный режим.
// Создаем новый элемент справочника ДополнительныеОтчетыИОбработки.
// Он будет использоваться как временный контейнер для нашей обработки.
НоваяОбработка = Справочники.ДополнительныеОтчетыИОбработки.СоздатьЭлемент();
// Задаем уникальное наименование для временного элемента.
// Рекомендуем использовать текущую дату и время, чтобы избежать конфликтов.
НоваяОбработка.Наименование = "ВременнаяЗагрузкаПрайса_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss");
// Указываем вид элемента: в нашем случае это "Обработка".
НоваяОбработка.Вид = ПредопределенноеЗначение("Перечисление.ВидыДополнительныхОтчетовИОбработок.Обработка");
// Публикуем обработку для использования.
НоваяОбработка.Публикация = Истина;
// Определяем вариант использования. Для регламентных заданий подойдет "ВФормеСправочника" или "Везде".
НоваяОбработка.Использование = ПредопределенноеЗначение("Перечисление.ВариантыИспользованияДополнительныхОтчетовИОбработок.ВФормеСправочника");
// Загружаем бинарные данные файла обработки в специальное хранилище.
// Используем сжатие для оптимизации места.
ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлуОбработки);
НоваяОбработка.ХранилищеФайла = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
// Важно: Отключаем безопасный режим.
// Это ключевой момент для запуска "небезопасных" обработок.
// Без этого флага сервер продолжит блокировать выполнение.
НоваяОбработка.БезопасныйРежим = Ложь;
// Реквизиты, которые могут быть полезны, но не обязательны для базового запуска:
// НоваяОбработка.ВерсияКонфигурации = "3.0.100.0"; // Пример версии конфигурации
// НоваяОбработка.ОбъектНазначения = <СсылкаНаОбъект>; // Если обработка привязана к конкретным объектам
После того как все реквизиты элемента справочника заполнены, мы можем записать его и вызвать команду на выполнение нашей внешней обработки.
Попытка
// Записываем новый элемент справочника. После этой операции обработка становится доступной
// для выполнения через механизм дополнительных отчетов и обработок.
НоваяОбработка.Записать();
// Определяем имя команды, которую должна выполнить обработка.
// Обычно это "Выполнить", но может быть и другое имя, определенное в самой обработке.
ИмяКоманды = "Выполнить";
КомандыОбработки = НоваяОбработка.ПолучитьКоманды();
// Проверяем, существует ли указанная команда в обработке.
Если КомандыОбработки.Найти(ИмяКоманды, "Имя") Тогда
// Вызываем команду внешней обработки.
// Это запускает ее выполнение в контексте сервера 1С.
ДополнительныеОтчетыИОбработки.ВыполнитьКоманду(НоваяОбработка.Ссылка, ИмяКоманды);
Сообщить("Обработка успешно выполнена.");
Иначе
Сообщить("Команда '" + ИмяКоманды + "' не найдена в обработке.", СтатусСообщения.Важное);
КонецЕсли;
Исключение
// Обрабатываем возможные ошибки, возникшие при записи или выполнении обработки.
Сообщить("Ошибка при выполнении обработки: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
Хорошей практикой является использование блоков Попытка-Исключение для обработки возможных сбоев и, при необходимости, удаление временного элемента справочника после завершения работы, чтобы не засорять базу данных.
// Удаляем временный элемент справочника после выполнения.
// Это помогает поддерживать порядок в базе данных и избегать накопления ненужных данных.
Попытка
НоваяОбработка.Удалить();
Сообщить("Временная обработка удалена.");
Исключение
// Если при удалении возникли ошибки, сообщаем об этом.
Сообщить("Ошибка при удалении временной обработки: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПозиции; // Опечатка в исходнике, исправим на КонецПроцедуры для завершения
КонецПроцедуры
Собираем все шаги вместе. Вот полный пример кода, который вы можете использовать в своем регламентном задании или любой другой серверной процедуре:
&НаСервере
Процедура ВыполнитьВнешнююОбработкуНаСервере()
// Путь к файлу внешней обработки на сервере.
// Убедитесь, что этот путь доступен для сервера 1С.
ПутьКФайлуОбработки = "C:\МоиОбработки\ЗагрузкаПрайса.epf";
// Шаг 1: Проверка существования файла
Если Не ФайлСуществует(ПутьКФайлуОбработки) Тогда
Сообщить("Файл обработки не найден: " + ПутьКФайлуОбработки, СтатусСообщения.Важное);
Возврат;
КонецЕсли;
// Переменная для ссылки на созданный элемент справочника
НоваяОбработка = Неопределено;
Попытка
// Шаг 2: Создаем новый элемент справочника ДополнительныеОтчетыИОбработки
НоваяОбработка = Справочники.ДополнительныеОтчетыИОбработки.СоздатьЭлемент();
НоваяОбработка.Наименование = "ВременнаяЗагрузкаПрайса_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss");
НоваяОбработка.Вид = ПредопределенноеЗначение("Перечисление.ВидыДополнительныхОтчетовИОбработок.Обработка");
НоваяОбработка.Публикация = Истина;
НоваяОбработка.Использование = ПредопределенноеЗначение("Перечисление.ВариантыИспользованияДополнительныхОтчетовИОбработок.ВФормеСправочника");
// Загружаем файл обработки в хранилище
ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлуОбработки);
НоваяОбработка.ХранилищеФайла = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
// Важно: Отключаем безопасный режим, если обработка требует этого
НоваяОбработка.БезопасныйРежим = Ложь;
// Эти реквизиты могут быть полезны, но не всегда обязательны
// НоваяОбработка.ВерсияКонфигурации = "3.0.100.0"; // Пример
// НоваяОбработка.ОбъектНазначения = <СсылкаНаОбъект>; // Если обработка привязана к каким-то объектам
// Шаг 3: Записываем элемент
НоваяОбработка.Записать();
// Находим команду, которую нужно выполнить. Обычно это "Выполнить"
ИмяКоманды = "Выполнить";
КомандыОбработки = НоваяОбработка.ПолучитьКоманды();
Если КомандыОбработки.Найти(ИмяКоманды, "Имя") Тогда
// Выполняем команду обработки
ДополнительныеОтчетыИОбработки.ВыполнитьКоманду(НоваяОбработка.Ссылка, ИмяКоманды);
Сообщить("Обработка успешно выполнена.");
Иначе
Сообщить("Команда '" + ИмяКоманды + "' не найдена в обработке.", СтатусСообщения.Важное);
КонецЕсли;
Исключение
// Шаг 4: Обработка ошибок
Сообщить("Ошибка при выполнении обработки: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
// Шаг 4 (продолжение): Удаление временного элемента справочника
// Выполняем удаление только если элемент был успешно создан и записан
Если НоваяОбработка <> Неопределено Тогда
Попытка
НоваяОбработка.Удалить();
Сообщить("Временная обработка удалена.");
Исключение
Сообщить("Ошибка при удалении временной обработки: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Для успешного выполнения описанного сценария крайне важно, чтобы пользователь, от имени которого запускается регламентное задание (или сеанс, если это фоновое задание), имел достаточные права. Мы рекомендуем:
ДополнительныеОтчетыИОбработки.Обратите внимание, что установка свойства БезопасныйРежим = Ложь отключает контроль безопасности для данной обработки. Мы должны быть полностью уверены в надежности и безопасности кода внешней обработки, которую запускаем таким способом. Запуск непроверенного кода с отключенным безопасным режимом может привести к серьезным проблемам с безопасностью и целостностью данных в вашей информационной базе.
Если вашей внешней обработке для работы требуются какие-либо параметры, вы можете передать их несколькими способами:
ДополнительныеОтчетыИОбработки.ВременноеХранилище или ХранилищеОбщихНастроек) перед вызовом обработки, а затем считать их изнутри самой обработки.Поскольку регламентные задания часто выполняются без непосредственного участия пользователя, крайне важно обеспечить адекватное логирование всех действий и ошибок. Включите подробное логирование в вашей внешней обработке, а также в обертке, которая ее запускает (как в нашем примере с Сообщить()). Это поможет нам оперативно выявлять и устранять проблемы.
Таким образом, мы видим, что, несмотря на ограничения безопасности сервера 1С, существует стандартный и надежный способ запуска внешних обработок через регламентные задания. Программное управление справочником ДополнительныеОтчетыИОбработки дает нам необходимый контроль и гибкость, позволяя автоматизировать сложные процессы в безопасной и управляемой среде.