При переходе на новые релизы платформы 1С:Предприятие 8.3 разработчики часто сталкиваются с ситуацией, когда внешняя обработка загрузки данных внезапно завершает работу аварийно. В журнале регистрации или в окне сообщения об ошибке появляется запись вида: «Ошибка при вызове метода контекста (ПолучитьCOMОбъект): Установлен безопасный режим. Выполнение операции запрещено». Подобное поведение также характерно для конструкций Новый COMОбъект и вызовов внешних программ через ЗапуститьПриложение.
Разберем детально, почему платформа блокирует эти операции, как устроена механика безопасного режима и какие существуют способы для корректного решения этой проблемы.
Проанализируем архитектурную логику платформы 1С. Безопасный режим предназначен для предотвращения несанкционированных действий со стороны потенциально опасного программного кода. Когда обработка запускается в безопасном режиме, платформа автоматически накладывает жесткие ограничения:
ПолучитьCOMОбъект и Новый COMОбъект.ЗапуститьПриложение становится недоступным.УстановитьПривилегированныйРежим(Истина) внутри безопасного контекста вызывает исключение.УстановитьБезопасныйРежим(Ложь). Снять ограничение может только тот уровень стека вызовов, на котором оно было установлено.Выясним причину, с которой столкнулся автор темы. Если внешняя обработка хранится как двоичные данные в реквизите справочника или во временном хранилище и создается программно разработчиком, платформа по умолчанию запускает ее в безопасном режиме. Рассмотрим синтаксис фабрики внешних обработок.
Для создания объекта из ранее подключенного файла или пути используется метод ВнешниеОбработки.Создать:
// Вторым параметром передается признак БезопасныйРежим (по умолчанию Истина)
ИмяФайла = "C:\Обработки\ЗагрузкаДанных.epf";
ОбработкаОбъект = ВнешниеОбработки.Создать(ИмяФайла, Ложь);
ОбработкаОбъект.ВыполнитьЗагрузку();
Если же файл предварительно помещается во временное хранилище и регистрируется через менеджер, применяется метод ВнешниеОбработки.Подключить. В нем за безопасность отвечает третий параметр:
// Третий параметр - БезопасныйРежим, четвертый - ЗащитаОтОпасныхДействий
ИмяОбработки = ВнешниеОбработки.Подключить(АдресВХранилище, , Ложь);
ОбработкаОбъект = ВнешниеОбработки.Создать(ИмяОбработки, Ложь);
ОбработкаОбъект.ВыполнитьЗагрузку();
Обратим внимание: передача значения Ложь в параметр БезопасныйРежим снимает блокировку на вызов COM-объектов, если сам вызывающий контекст на сервере не был запущен в безопасном режиме.
Если обработка подключается через типовую подсистему «Дополнительные отчеты и обработки», простого добавления свойства в модуль объекта недостаточно. Разберем по шагам, почему функция СведенияОВнешнейОбработке не срабатывает мгновенно.
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.БезопасныйРежим = Ложь; // Отключаем безопасный режим
// Заполнение команд...
Возврат ПараметрыРегистрации;
КонецФункции
ДополнительныеОтчетыИОбработки при первой загрузке. Изменение кода в файле не обновляет значения в базе автоматически.Бывают ситуации, когда архитектурно требуется оставить внешнюю обработку в безопасном режиме, но выполнить чтение COM-объекта необходимо. В этом случае применим архитектурный шаблон делегирования вызова на сторону конфигурации или расширения.
Создадим или используем общий модуль со свойствами «Сервер» и «Привилегированный». Код, исполняемый в привилегированном модуле, игнорирует ограничения безопасного режима вызывающей обработки. Посмотрим на пример реализации экспортной функции:
// В общем модуле с установленным признаком "Привилегированный"
Функция ПолучитьДанныеЧерезCOM(ПутьКФайлу) Экспорт
// В привилегированном модуле можно явно отключить безопасный режим для блока
УстановитьОтключениеБезопасногоРежима(Истина);
Попытка
COMОбъект = ПолучитьCOMОбъект(ПутьКФайлу);
// Выполняем чтение данных...
Возврат РезультатТаблица;
Исключение
ВызватьИсключение НСтр("ru = 'Не удалось инициализировать COM-объект: '") + ОписаниеОшибки();
КонецПопытки;
КонецФункции
Из внешней обработки достаточно вызвать эту экспортную функцию. Это позволяет соблюсти безопасность основной логики и точечно разрешить внешнюю интеграцию.
Если база данных работает в клиент-серверном режиме и в кластере включены профили безопасности, платформа контролирует обращения к COM независимо от параметров метода Создать(). Проанализируем действия системного администратора в консоли кластера 1С:
Excel.Application).Использование COM-объектов на стороне сервера 1С часто сопряжено с проблемами разрядности (32/64 бит) и зависанием процессов сторонних приложений в памяти. Если COM используется для загрузки файлов Excel, Word или XML, рассмотрим платформенные альтернативы, которые полностью совместимы с безопасным режимом:
ТабличныйДокумент.Прочитать(), который работает быстро, не требует установленного пакета Microsoft Office и не вызывает конфликтов с безопасным режимом:
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу);
// Обработка строк и ячеек документа
ЧтениеXML, ЧтениеJSON, ЧтениеZIPФайла.&НаКлиенте. На клиенте вызовы COM выполняются в окружении локального пользователя Windows, где проще управлять разрядностью библиотек и правами доступа.