Запуск фонового задания во внешней обработке. Отключение предупреждений защиты от опасных действий в фоновом задании

Как запустить фоновое задание из модуля внешней обработки используя БСП. Как отключить безопасный режим и сообщения защиты от опасных действий независимо от профиля безопасности пользователя в фоновом задании во внешней обработке.

1. Как запустить фоновое задание из модуля внешней обработки используя БСП

 

После тщетных попыток запустить в фоне процедуру модуля объекта внешней обработки, я все-таки решил глубже копнуть все механизмы длительных операций БСП. Все процедуры выполнения кода в фоне из подсистемы "Длительные операции" работают на сервере. То есть все происходит так: берется внешняя обработка, хранящаяся в справочнике "ДополнительныеОтчетыИОбработки", разворачивается на сервере (вот тут ключевой момент) и из этого экземпляра обработки выполняются указанные процедуры / функции модуля объекта (см. процедуру "ЗапуститьФоновоеЗаданиеСКонтекстомКлиента" модуля "ДлительныеОперации" БСП 3.х). Если вы вызываете ту же самую обработку из "файл-открыть", то БСП тупо пытается запустить указанные методы из обработки на сервере, в то время как обработка находится на клиенте.

 

Выходом было создать копию внешней обработки на сервере и запустить процедуру ее (копии) модуля объекта в фоне. Для этого, при открытии формы я помещал обработку во временное хранилище и тут же создавал копию на сервере в временном файле. Имя файла на сервере хранил в реквизите формы.

&НаКлиенте
Процедура ПриОткрытии(Отказ)

Если ЭтоВнешняяОбработка() Тогда
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьРезультатПомещенияФайлаОбработки", ЭтотОбъект);
НачатьПомещениеФайлов(ОписаниеОповещения, ИмяФайлаОбработки(), Ложь, УникальныйИдентификатор);
КонецЕсли;

КонецПроцедуры

&НаКлиенте
Процедура ОбработатьРезультатПомещенияФайлаОбработки(ПомещенныеФайлы, ОбработчикЗавершения) Экспорт

Если ПомещенныеФайлы <> Неопределено Тогда
// Создаем копию текущией обработки на сервере
ХранениеФайлаОбработки = КопияОбработкиНаСервере(ПомещенныеФайлы[0].Хранение);
КонецЕсли;

КонецПроцедуры

&НаСервере
Функция КопияОбработкиНаСервере(Хранение)

Результат = ПолучитьИмяВременногоФайла();
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Хранение);
ДвоичныеДанные.Записать(Результат);

Возврат Результат;

КонецФункции

&НаСервере
Функция ИмяФайлаОбработки()

Возврат РеквизитФормыВЗначение("Объект").ИспользуемоеИмяФайла;

КонецФункции

&НаСервере
Функция ЭтоВнешняяОбработка()

ЧастиИмени = СтрРазделить(РеквизитФормыВЗначение("Объект").Метаданные().ПолноеИмя(), ".");
Возврат (ВРег(ЧастиИмени[0]) = "ВНЕШНЯЯОБРАБОТКА")

КонецФункции

Ну вот, собственно и все. Осталось только правильно вызвать процедуру из модуля объекта копии обработки на сервере.

&НаКлиенте
Процедура НачатьВыполнениеФоновогоЗадания()

// Указываете свои параметры выполнения фонового задания....

ОповещениеОПрогрессеВыполнения = Новый ОписаниеОповещения("<ОповещениеОПрогрессеВыполнения>", ЭтотОбъект);

ДлительнаяОперация = НачатьВыполнениеФоновогоЗаданияНаСервере();

ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.ТекстСообщения = <...>;
ПараметрыОжидания.ВыводитьПрогрессВыполнения = <...>;
ПараметрыОжидания.ОповещениеОПрогрессеВыполнения = ОповещениеОПрогрессеВыполнения;
ПараметрыОжидания.ОповещениеПользователя.Показать = <...>;
ПараметрыОжидания.ВыводитьОкноОжидания = <...>;
ПараметрыОжидания.ВыводитьСообщения = <...>;

ОповещениеОЗавершении = Новый ОписаниеОповещения("<ОповещениеОЗавершении>", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);

КонецПроцедуры


&НаСервере
Функция НачатьВыполнениеФоновогоЗаданияНаСервере()

ПараметрыВыполненияОбработки = Новый Структура;
// Здесь указываете параметры, передаваемые в процедуру, выполняемую в фоне
// ....
// ...

// Остальной код можно оставлять, как есть, не забыв указать имя фоновой процедуры и ее описание

ЭтоВнешняяОбработка = ЭтоВнешняяОбработка();
ИмяОбработки = ?(ЭтоВнешняяОбработка, ХранениеФайлаОбработки, РеквизитФормыВЗначение("Объект").Метаданные().ПолноеИмя());

ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("ИмяОбработки",  ИмяОбработки);
ПараметрыЗадания.Вставить("ИмяМетода",   "<Имя процедуры в модуле объекта>");
ПараметрыЗадания.Вставить("ПараметрыВыполнения", ПараметрыВыполненияОбработки);
ПараметрыЗадания.Вставить("ЭтоВнешняяОбработка", ЭтоВнешняяОбработка);

ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = '<Описание вашего фонового задания>'");
ПараметрыВыполнения.ЗапуститьВФоне = Истина;
ПараметрыВыполнения.Вставить("ИдентификаторФормы", УникальныйИдентификатор);

ВыполняемыйМетод = "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки"; // Выполняем процедуру из модуля объекта
Возврат ДлительныеОперации.ВыполнитьВФоне(ВыполняемыйМетод, ПараметрыЗадания, ПараметрыВыполнения);

КонецФункции

 

2. Как отключить безопасный режим и сообщения защиты от опасных действий независимо от профиля безопасности пользователя в фоновом задании во внешней обработке

 

Ниже приведенный способ, используемый мной, не является идеальным, но прекрасно работает и используется мной уже не один год.

Я думаю, что многим приходилось сталкиваться с тем, что на сервере надо было подтвердить разрешение на запуск com-соединения. И все выключали защиту от опасных действий в профиле пользователя, чего делать не рекомендуется. Я пошел другим путем. Создаю две экспортные процедуры в модуле объекта внешней обработки: одна — непосредственно функция, которая будет выполнять необходимые действия и другая, которая вызовет первую с отключенным контролем прав доступа профиля.

Выглядит это так:

Функция ОбработкаДанных(...) Экспорт

...

КонецФункции

Процедура ОбработкаДанныхВФоне(Параметры, АдресРезультата) Экспорт

ЧастиИмени = СтрРазделить(ЭтотОбъект.Метаданные().ПолноеИмя(), ".");
ЭтоВнешняяОбработка = (ВРег(ЧастиИмени[0]) = "ВНЕШНЯЯОБРАБОТКА");
Если ЭтоВнешняяОбработка Тогда
ОбработкаОбъект = ВнешниеОбработки.Создать(ЭтотОбъект.ИспользуемоеИмяФайла, Ложь, ОбщегоНазначения.ОписаниеЗащитыБезПредупреждений());
Результат = ОбработкаОбъект.ОбработкаДанных(...);
Иначе
Результат = ОбработкаДанных(...);
КонецЕсли;

ПоместитьВоВременноеХранилище(Результат, АдресРезультата);

КонецПроцедуры

То есть, я создал еще один экземпляр самой себя без контроля прав (не в безопасном режиме и с отключением предупреждений защиты от опасных действий).

Пример использования, созданный из обработки демонстрационной конфигурации БСП прилагается (создавалась на платформе 8.3.13.1513, совместима с любой платформой 8.3, которая поддерживает БСП 3.0 и старше)

 

Предупреждение. Нельзя использовать реквизиты и табличные части внешней обработке в процедурах/функциях, выполняемых в фоне. Данные реквизиты должны быть переданы непосредственно в вызываемую процедуру/функцию из модуля формы.

 

19 Comments

  1. jONES1979

    «капнуть» -> «копнуть»

    Reply
  2. jONES1979

    (2) «не грамотный» -> «неграмотный»

    Но теперь-то грамотный! А грамотность — это первое впечатление! И отсутствие подсознательного раздражения от читаемого текста.



    Я забыл что оказывается здесь нельзя почистить комменты. Ну тогда сорри, в другой раз в личку напишу)

    Reply
  3. BenGunn

    (3) Мне гораздо больше нравится мысль, что подобное еще никто не делал (если даже и сделал, то не говорит об этом).

    Reply
  4. BenGunn

    (3)

    «Неграмотный» или «не грамотный»: слитно или раздельно?

    Если коротко, то пишется слитно, когда утверждается безграмотность, и пишется раздельно, когда отрицается грамотность.

    Он неграмотный. (Утверждается безграмотность).

    Он не грамотный. (Отрицается грамотность).

    (Этот принцип действует и для наречия «неграмотно»).

    Reply
  5. PerlAmutor

    Спасибо. Довольно интересные трюки.

    Reply
  6. BenGunn

    (3) Да ну, нафиг! Посмотрел твой профиль… Да ты, оказывается, флудер! Сказать только ради того, чтобы сказать?! Отличная позиция! А не хочешь сделать что-нибудь полезное? Ну, кроме того, что раздувать щеки с умным видом?!

    Reply
  7. BenGunn

    (6) Спасибо!

    Reply
  8. jONES1979

    (7) Зачем переходить на личности, вам скучно? За полезное на работе деньги платят, а не звёздочки в интернете. Форум — это по определению место для общения, что позволяет отвлечься. Кого первого-то на флудеразм пробило? Поправили бы свою опечатку и копали дальше,.. а не капали.

    За статью спасибо, кстати. С моей помощью теперь она чуть ли не идеальна))

    Reply
  9. BenGunn

    (9)

    Ну я говорю, флудер!

    Кстати, где ты здесь видишь форум? Здесь специалисты делятся знаниями, а не ищут орфографические ошибки. Теми самыми знаниями, кстати, которые кто-нибудь использует в той самой работе, за которую деньги платят. А судя по тому, что пишешь в коментах, тебе еще очень далеко до такого уровня… Поищи развлекуху где-нибудь на Фейсбуке, там таких как ты любят

    Reply
  10. jONES1979

    (10)

    — К чему эти ярлыки? Не опускайтесь до моего уровня!

    — Форум написано вверху.

    — Я не искал ошибок, они сами бросаются в глаза и сбивают восприятие.

    — За знания я никогда не устану говорить спасибо! Спасибо!

    Reply
  11. Oldsad

    отличная статья

    Reply
  12. fomix

    1. Изменились параметры процедуры «НачатьПомещениеФайлов», поэтому код процедуры «ПриОткрытии» будет таким (по крайней мере для 1С:Предприятие 8.3 (8.3.12.1685), БП 3.0):

    &НаКлиенте
    Процедура ПриОткрытии(Отказ)
    
    ОписаниеФайлаВО = Новый ОписаниеПередаваемогоФайла(ИмяФайлаОбработки());
    
    ПомещаемыеФайлы = Новый Массив;
    ПомещаемыеФайлы.Добавить(ОписаниеФайлаВО);
    
    Если ЭтоВнешняяОбработка() Тогда
    ОписаниеОповещения = Новый ОписаниеОповещения(«ОбработатьРезультатПомещенияФайлаОбработки», ЭтотОбъект);
    НачатьПомещениеФайлов(ОписаниеОповещения, ПомещаемыеФайлы,, Ложь, УникальныйИдентификатор);
    КонецЕсли;
    
    КонецПроцедуры

    Показать

    2. Выполнения скрипта из COMОбъект(«WScript.Shell») требует особых прав и без подтверждения такого действия на сервере не работает! Соответственно, ваша обработка не отрабатывает и каждый раз вываливается запрос на подтверждение((( Можно просто поставить вместо этого цикл.

    Reply
  13. BenGunn

    (13) Уточни, пожалуйста, что имелось в виду по п.2

    Reply
  14. BenGunn

    (13) По п.1, тестировалось на 8.3.13.1513. Что на более ранних релизах, сказать не могу. На поздних работает

    Reply
  15. fomix

    (15) Платформа тут не при чем! В последнем релизе БП 3.0 (и скорее всего и в других конфигурациях тоже!) изменился вызов команды «НачатьПомещениеФайлов»

    Reply
  16. fomix

    (14) При попытке выполнить скрипт, 1с-ка стандартно спрашивает «…пытается выполнить вызов команды WScript.Shell. Подтверждаете? Да/Нет». Отвечаешь Да и по-новой вываливается этот диалог и так до посинения. Ну тебе это нужно было для «тормоза», поэтому в реальной жизни вряд ли кому-то пригодится. Так что, не заморачивайся!

    Reply
  17. BenGunn

    (17) Точно! Фоновое задание при таком подходе запускается от имени DefUser, соответственно, COM объекты создаются только в безопасном профиле…. Ёкрныйбабай! Сам на этом споткнулся! Есть предложения по решению вопроса? (Ну, кроме того, что включать процедуру фонового задания в конфу)?

    Reply
  18. BenGunn

    (16) Ничё не понял… При чем тут вообще БП?

    Глобальный контекст (Global context)

    НачатьПомещениеФайлов (BeginPuttingFiles)

    Синтаксис:

    НачатьПомещениеФайлов(<ОписаниеОповещенияОЗавершении>, <ПомещаемыеФайлы>, <Интерактивно>, <УникальныйИдентификаторФормы>, <ОписаниеОповещенияПередНачаломПомещенияФайлов>)

    Reply
  19. fomix

    (19) Насчет БП точно — я не прав! Платформа 8.3.15.1700:

    Все верно про синтаксис:

    НачатьПомещениеФайлов(<ОписаниеОповещенияОЗавершении>, <ПомещаемыеФайлы>, <Интерактивно>, <УникальныйИдентификаторФормы>, <ОписаниеОповещенияПередНачаломПомещенияФайлов>)

    Но у вас параметр: <ПомещаемыеФайлы> = РеквизитФормыВЗначение(«Объект»).ИспользуемоеИмяФайла (тип строка). Так не работает!

    А вот как я написал:

    ОписаниеФайлаВО = Новый ОписаниеПередаваемогоФайла(ИмяФайлаОбработки());
    ПомещаемыеФайлы = Новый Массив;
    ПомещаемыеФайлы.Добавить(ОписаниеФайлаВО)

    работает..

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *