1. Как запустить фоновое задание из модуля внешней обработки используя БСП
После тщетных попыток запустить в фоне процедуру модуля объекта внешней обработки, я все-таки решил глубже копнуть все механизмы длительных операций БСП. Все процедуры выполнения кода в фоне из подсистемы "Длительные операции" работают на сервере. То есть все происходит так: берется внешняя обработка, хранящаяся в справочнике "ДополнительныеОтчетыИОбработки", разворачивается на сервере (вот тут ключевой момент) и из этого экземпляра обработки выполняются указанные процедуры / функции модуля объекта (см. процедуру "ЗапуститьФоновоеЗаданиеСКонтекстомКлиента" модуля "ДлительныеОперации" БСП 3.х). Если вы вызываете ту же самую обработку из "файл-открыть", то БСП тупо пытается запустить указанные методы из обработки на сервере, в то время как обработка находится на клиенте.
Выходом было создать копию внешней обработки на сервере и запустить процедуру ее (копии) модуля объекта в фоне. Для этого, при открытии формы я помещал обработку во временное хранилище и тут же создавал копию на сервере в временном файле. Имя файла на сервере хранил в реквизите формы.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ЭтоВнешняяОбработка() Тогда
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьРезультатПомещенияФайлаОбработки", ЭтотОбъект);
НачатьПомещениеФайлов(ОписаниеОповещения, ИмяФайлаОбработки(), Ложь, УникальныйИдентификатор);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьРезультатПомещенияФайлаОбработки(ПомещенныеФайлы, ОбработчикЗавершения) Экспорт
Если ПомещенныеФайлы <> Неопределено Тогда
// Создаем копию текущией обработки на сервере
ХранениеФайлаОбработки = КопияОбработкиНаСервере(ПомещенныеФайлы[0].Хранение);
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция КопияОбработкиНаСервере(Хранение)
Результат = ПолучитьИмяВременногоФайла();
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Хранение);
ДвоичныеДанные.Записать(Результат);
Возврат Результат;
КонецФункции
&НаСервере
Функция ИмяФайлаОбработки()
Возврат РеквизитФормыВЗначение("Объект").ИспользуемоеИмяФайла;
КонецФункции
&НаСервере
Функция ЭтоВнешняяОбработка()
ЧастиИмени = СтрРазделить(РеквизитФормыВЗначение("Объект").Метаданные().ПолноеИмя(), ".");
Возврат (ВРег(ЧастиИмени[0]) = "ВНЕШНЯЯОБРАБОТКА")
КонецФункции
Ну вот, собственно и все. Осталось только правильно вызвать процедуру из модуля объекта копии обработки на сервере.
&НаКлиенте
Процедура НачатьВыполнениеФоновогоЗадания()
// Указываете свои параметры выполнения фонового задания....
ОповещениеОПрогрессеВыполнения = Новый ОписаниеОповещения("<ОповещениеОПрогрессеВыполнения>", ЭтотОбъект);
ДлительнаяОперация = НачатьВыполнениеФоновогоЗаданияНаСервере();
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.ТекстСообщения = <...>;
ПараметрыОжидания.ВыводитьПрогрессВыполнения = <...>;
ПараметрыОжидания.ОповещениеОПрогрессеВыполнения = ОповещениеОПрогрессеВыполнения;
ПараметрыОжидания.ОповещениеПользователя.Показать = <...>;
ПараметрыОжидания.ВыводитьОкноОжидания = <...>;
ПараметрыОжидания.ВыводитьСообщения = <...>;
ОповещениеОЗавершении = Новый ОписаниеОповещения("<ОповещениеОЗавершении>", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);
КонецПроцедуры
&НаСервере
Функция НачатьВыполнениеФоновогоЗаданияНаСервере()
ПараметрыВыполненияОбработки = Новый Структура;
// Здесь указываете параметры, передаваемые в процедуру, выполняемую в фоне
// ....
// ...
// Остальной код можно оставлять, как есть, не забыв указать имя фоновой процедуры и ее описание
ЭтоВнешняяОбработка = ЭтоВнешняяОбработка();
ИмяОбработки = ?(ЭтоВнешняяОбработка, ХранениеФайлаОбработки, РеквизитФормыВЗначение("Объект").Метаданные().ПолноеИмя());
ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("ИмяОбработки", ИмяОбработки);
ПараметрыЗадания.Вставить("ИмяМетода", "<Имя процедуры в модуле объекта>");
ПараметрыЗадания.Вставить("ПараметрыВыполнения", ПараметрыВыполненияОбработки);
ПараметрыЗадания.Вставить("ЭтоВнешняяОбработка", ЭтоВнешняяОбработка);
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = '<Описание вашего фонового задания>'");
ПараметрыВыполнения.ЗапуститьВФоне = Истина;
ПараметрыВыполнения.Вставить("ИдентификаторФормы", УникальныйИдентификатор);
ВыполняемыйМетод = "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки"; // Выполняем процедуру из модуля объекта
Возврат ДлительныеОперации.ВыполнитьВФоне(ВыполняемыйМетод, ПараметрыЗадания, ПараметрыВыполнения);
КонецФункции
2. Как отключить безопасный режим и сообщения защиты от опасных действий независимо от профиля безопасности пользователя в фоновом задании во внешней обработке
Ниже приведенный способ, используемый мной, не является идеальным, но прекрасно работает и используется мной уже не один год.
Я думаю, что многим приходилось сталкиваться с тем, что на сервере надо было подтвердить разрешение на запуск com-соединения. И все выключали защиту от опасных действий в профиле пользователя, чего делать не рекомендуется. Я пошел другим путем. Создаю две экспортные процедуры в модуле объекта внешней обработки: одна - непосредственно функция, которая будет выполнять необходимые действия и другая, которая вызовет первую с отключенным контролем прав доступа профиля.
Выглядит это так:
Функция ОбработкаДанных(...) Экспорт
...
КонецФункции
Процедура ОбработкаДанныхВФоне(Параметры, АдресРезультата) Экспорт
ЧастиИмени = СтрРазделить(ЭтотОбъект.Метаданные().ПолноеИмя(), ".");
ЭтоВнешняяОбработка = (ВРег(ЧастиИмени[0]) = "ВНЕШНЯЯОБРАБОТКА");
Если ЭтоВнешняяОбработка Тогда
ОбработкаОбъект = ВнешниеОбработки.Создать(ЭтотОбъект.ИспользуемоеИмяФайла, Ложь, ОбщегоНазначения.ОписаниеЗащитыБезПредупреждений());
Результат = ОбработкаОбъект.ОбработкаДанных(...);
Иначе
Результат = ОбработкаДанных(...);
КонецЕсли;
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецПроцедуры
То есть, я создал еще один экземпляр самой себя без контроля прав (не в безопасном режиме и с отключением предупреждений защиты от опасных действий).
Пример использования, созданный из обработки демонстрационной конфигурации БСП прилагается (создавалась на платформе 8.3.13.1513, совместима с любой платформой 8.3, которая поддерживает БСП 3.0 и старше)
Предупреждение. Нельзя использовать реквизиты и табличные части внешней обработке в процедурах/функциях, выполняемых в фоне. Данные реквизиты должны быть переданы непосредственно в вызываемую процедуру/функцию из модуля формы.