При разработке и сопровождении конфигураций на платформе 1С:Предприятие разработчики часто сталкиваются с ситуацией: внешняя обработка успешно читает данные, но при попытке записать файл на диск сервера, запустить системную команду или обратиться к COM-объекту падает с критической ошибкой «Установлен безопасный режим. Выполнение операции запрещено».
Первая интуитивная попытка исправить ситуацию — написать в коде самой обработки конструкцию:
Если БезопасныйРежим() Тогда
УстановитьБезопасныйРежим(Ложь);
КонецЕсли;
Однако такой вызов приводит к новой ошибке времени выполнения. Давайте подробно разберем, как устроен механизм безопасности платформы 1С, почему безопасный режим нельзя просто отключить строчкой кода и какие существуют корректные способы решения этой задачи.
Проанализируем механику работы метода УстановитьБезопасныйРежим(). В платформе 1С этот механизм функционирует по принципу парного стека вызовов в пределах одного контекста (конкретной процедуры или функции):
УстановитьБезопасныйРежим(Ложь) может быть вызван исключительно в том случае, если ранее в этой же самой процедуре или функции был выполнен вызов УстановитьБезопасныйРежим(Истина). Если количество вызовов с параметром Ложь превышает количество предшествующих вызовов с параметром Истина в текущем контексте, платформа немедленно генерирует исключение.Посмотрим на пример правильного локального использования безопасного режима внутри кода конфигурации:
Процедура ВыполнитьНедоверенныйАлгоритм()
// Включаем безопасный режим перед выполнением опасного участка
УстановитьБезопасныйРежим(Истина);
Попытка
// Выполнение потенциально небезопасного кода
Выполнить(НекийВнешнийТекст);
Исключение
// Обязательно возвращаем исходное состояние в случае ошибки
УстановитьБезопасныйРежим(Ложь);
ВызватьИсключение;
КонецПопытки;
// Выключаем безопасный режим в той же процедуре
УстановитьБезопасныйРежим(Ложь);
КонецПроцедуры
Если внешняя обработка уже была запущена в безопасном режиме, вызов функции БезопасныйРежим() вернет Истина, однако снять этот флаг изнутри модуля обработки невозможно, так как он был установлен внешним контекстом.
Выясним, какие именно операции блокируются платформой при активном безопасном режиме:
ДвоичныеДанные.Записать(ПутьНаСервере) завершается аварийно.УстановитьПривилегированныйРежим(Истина) полностью игнорируются либо вызывают исключительную ситуацию.ЗапуститьПриложение() и КомандаСистемы().Новый COMОбъект(...) и загрузка сторонних библиотек.Разберем основные сценарии, при которых код начинает выполняться в безопасном режиме без явного вызова функции разработчиком:
ВнешниеОбработки.Создать() или ВнешниеОбработки.Подключить() параметр безопасного режима по умолчанию часто принимает значение Истина.Рассмотрим по шагам практические способы решения проблемы в зависимости от архитектуры вашей базы данных.
Если внешняя обработка запускается программно из кода конфигурации или другой обработки, проверим параметры методов менеджера внешних обработок. При создании или подключении обработки необходимо явно передать параметр Ложь в позицию безопасного режима.
Разберем пример создания объекта из файла на диске:
// Второй параметр метода Создать() определяет признак безопасного режима
ПутьКОбработке = "C:\Обработки\ЗагрузкаДанных.epf";
ОбработкаОбъект = ВнешниеОбработки.Создать(ПутьКОбработке, Ложь);
ОбработкаОбъект.ВыполнитьЗагрузку();
Посмотрим на пример подключения обработки из временного хранилища на сервере:
// Третий параметр метода Подключить() отвечает за безопасный режим
ИмяОбработки = ВнешниеОбработки.Подключить(АдресВоВременномХранилище, , Ложь);
ОбработкаОбъект = ВнешниеОбработки.Создать(ИмяОбработки, Ложь);
ОбработкаОбъект.ЗапуститьОбработку();
Если обработка должна запускаться рядовыми пользователями без прав администратора через диалог открытия файлов, снять безопасный режим с внешней обработки не удастся. В этом случае правильным архитектурным решением будет вынос опасных операций (например, записи файлов на диск сервера) в общий модуль конфигурации.
Разберем реализацию по шагам:
ФайловыеОперацииСервер).
// Процедура в общем модуле ФайловыеОперацииСервер
Процедура СохранитьФайлНаСервере(ДвоичныеДанные, ПутьНаСервере) Экспорт
ДвоичныеДанные.Записать(ПутьНаСервере);
КонецПроцедуры
// Код внутри внешней обработки
ПутьНаСервере = КаталогВременныхФайлов() + "loaddetali.xml";
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременногоХранилища);
// Вызываем процедуру общего модуля конфигурации вместо прямой записи
ФайловыеОперацииСервер.СохранитьФайлНаСервере(ДвоичныеДанные, ПутьНаСервере);
Код общих модулей конфигурации выполняется в доверенном контексте и не наследует ограничения безопасного режима внешней обработки.
Если конфигурация разработана с использованием Библиотеки Стандартных Подсистем (БСП), внешняя обработка должна содержать экспортную функцию СведенияОВнешнейОбработке() в модуле объекта.
Посмотрим на пример структуры описания обработки с отключением безопасного режима:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("Вид", "ДополнительнаяОбработка");
ПараметрыРегистрации.Вставить("Наименование", "Загрузка деталей");
ПараметрыРегистрации.Вставить("Версия", "1.0");
ПараметрыРегистрации.Вставить("БезопасныйРежим", Ложь);
ПараметрыРегистрации.Вставить("Информация", "Обработка загрузки файлов XML");
ТаблицаКоманд = Новый ТаблицаЗначений;
ТаблицаКоманд.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка"));
ТаблицаКоманд.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка"));
ТаблицаКоманд.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Идентификатор = "ЗагрузитьДанные";
НоваяКоманда.Использование = "ВызовСерверногоМетода";
НоваяКоманда.Представление = "Загрузить данные из XML";
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции
Важно: если обработка уже была ранее загружена в справочник «Дополнительные отчеты и обработки», изменение кода функции СведенияОВнешнейОбработке() не отключит безопасный режим автоматически. Администратору необходимо зайти в элемент справочника и вручную снять флаг Безопасный режим в карточке обработки.
При настройке прав часто путают два независимых механизма платформы:
Таким образом, для устранения ошибки записи файлов на сервере необходимо либо передавать Ложь при программном создании объекта ВнешняяОбработка, либо выносить файловые операции в доверенные серверные модули конфигурации.