1. Как запустить фоновое задание из модуля внешней обработки используя БСП
После тщетных попыток запустить в фоне процедуру модуля объекта внешней обработки, я все-таки решил глубже копнуть все механизмы длительных операций БСП. Все процедуры выполнения кода в фоне из подсистемы "Длительные операции" работают на сервере. То есть все происходит так: берется внешняя обработка, хранящаяся в справочнике "ДополнительныеОтчетыИОбработки", разворачивается на сервере (вот тут ключевой момент) и из этого экземпляра обработки выполняются указанные процедуры / функции модуля объекта (см. процедуру "ЗапуститьФоновоеЗаданиеСКонтекстомКлиента" модуля "ДлительныеОперации" БСП 3.х). Если вы вызываете ту же самую обработку из "файл-открыть", то БСП тупо пытается запустить указанные методы из обработки на сервере, в то время как обработка находится на клиенте.
Выходом было создать копию внешней обработки на сервере и запустить процедуру ее (копии) модуля объекта в фоне. Для этого, при открытии формы я помещал обработку во временное хранилище и тут же создавал копию на сервере в временном файле. Имя файла на сервере хранил в реквизите формы.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ЭтоВнешняяОбработка() Тогда
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьРезультатПомещенияФайлаОбработки", ЭтотОбъект);
НачатьПомещениеФайлов(ОписаниеОповещения, ИмяФайлаОбработки(), Ложь, УникальныйИдентификатор);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьРезультатПомещенияФайлаОбработки(ПомещенныеФайлы, ОбработчикЗавершения) Экспорт
Если ПомещенныеФайлы <> Неопределено Тогда
// Создаем копию текущией обработки на сервере
ХранениеФайлаОбработки = КопияОбработкиНаСервере(ПомещенныеФайлы[0].Хранение);
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция КопияОбработкиНаСервере(Хранение)
Результат = ПолучитьИмяВременногоФайла();
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Хранение);
ДвоичныеДанные.Записать(Результат);
Возврат Результат;
КонецФункции
&НаСервере
Функция ИмяФайлаОбработки()
Возврат РеквизитФормыВЗначение("Объект").ИспользуемоеИмяФайла;
КонецФункции
&НаСервере
Функция ЭтоВнешняяОбработка()
ЧастиИмени = СтрРазделить(РеквизитФормыВЗначение("Объект").Метаданные().ПолноеИмя(), ".");
Возврат (ВРег(ЧастиИмени[0]) = "ВНЕШНЯЯОБРАБОТКА")
КонецФункции
Ну вот, собственно и все. Осталось только правильно вызвать процедуру из модуля объекта копии обработки на сервере.
&НаКлиенте
Процедура НачатьВыполнениеФоновогоЗадания()
// Указываете свои параметры выполнения фонового задания....
ОповещениеОПрогрессеВыполнения = Новый ОписаниеОповещения("<ОповещениеОПрогрессеВыполнения>", ЭтотОбъект);
ДлительнаяОперация = НачатьВыполнениеФоновогоЗаданияНаСервере();
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.ТекстСообщения = <...>;
ПараметрыОжидания.ВыводитьПрогрессВыполнения = <...>;
ПараметрыОжидания.ОповещениеОПрогрессеВыполнения = ОповещениеОПрогрессеВыполнения;
ПараметрыОжидания.ОповещениеПользователя.Показать = <...>;
ПараметрыОжидания.ВыводитьОкноОжидания = <...>;
ПараметрыОжидания.ВыводитьСообщения = <...>;
ОповещениеОЗавершении = Новый ОписаниеОповещения("<ОповещениеОЗавершении>", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);
КонецПроцедуры
&НаСервере
Функция НачатьВыполнениеФоновогоЗаданияНаСервере()
ПараметрыВыполненияОбработки = Новый Структура;
// Здесь указываете параметры, передаваемые в процедуру, выполняемую в фоне
// ....
// ...
// Остальной код можно оставлять, как есть, не забыв указать имя фоновой процедуры и ее описание
ЭтоВнешняяОбработка = ЭтоВнешняяОбработка();
ИмяОбработки = ?(ЭтоВнешняяОбработка, ХранениеФайлаОбработки, РеквизитФормыВЗначение("Объект").Метаданные().ПолноеИмя());
ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("ИмяОбработки", ИмяОбработки);
ПараметрыЗадания.Вставить("ИмяМетода", "<Имя процедуры в модуле объекта>");
ПараметрыЗадания.Вставить("ПараметрыВыполнения", ПараметрыВыполненияОбработки);
ПараметрыЗадания.Вставить("ЭтоВнешняяОбработка", ЭтоВнешняяОбработка);
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = '<Описание вашего фонового задания>'");
ПараметрыВыполнения.ЗапуститьВФоне = Истина;
ПараметрыВыполнения.Вставить("ИдентификаторФормы", УникальныйИдентификатор);
ВыполняемыйМетод = "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки"; // Выполняем процедуру из модуля объекта
Возврат ДлительныеОперации.ВыполнитьВФоне(ВыполняемыйМетод, ПараметрыЗадания, ПараметрыВыполнения);
КонецФункции
2. Как отключить безопасный режим и сообщения защиты от опасных действий независимо от профиля безопасности пользователя в фоновом задании во внешней обработке
Ниже приведенный способ, используемый мной, не является идеальным, но прекрасно работает и используется мной уже не один год.
Я думаю, что многим приходилось сталкиваться с тем, что на сервере надо было подтвердить разрешение на запуск com-соединения. И все выключали защиту от опасных действий в профиле пользователя, чего делать не рекомендуется. Я пошел другим путем. Создаю две экспортные процедуры в модуле объекта внешней обработки: одна — непосредственно функция, которая будет выполнять необходимые действия и другая, которая вызовет первую с отключенным контролем прав доступа профиля.
Выглядит это так:
Функция ОбработкаДанных(...) Экспорт
...
КонецФункции
Процедура ОбработкаДанныхВФоне(Параметры, АдресРезультата) Экспорт
ЧастиИмени = СтрРазделить(ЭтотОбъект.Метаданные().ПолноеИмя(), ".");
ЭтоВнешняяОбработка = (ВРег(ЧастиИмени[0]) = "ВНЕШНЯЯОБРАБОТКА");
Если ЭтоВнешняяОбработка Тогда
ОбработкаОбъект = ВнешниеОбработки.Создать(ЭтотОбъект.ИспользуемоеИмяФайла, Ложь, ОбщегоНазначения.ОписаниеЗащитыБезПредупреждений());
Результат = ОбработкаОбъект.ОбработкаДанных(...);
Иначе
Результат = ОбработкаДанных(...);
КонецЕсли;
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецПроцедуры
То есть, я создал еще один экземпляр самой себя без контроля прав (не в безопасном режиме и с отключением предупреждений защиты от опасных действий).
Пример использования, созданный из обработки демонстрационной конфигурации БСП прилагается (создавалась на платформе 8.3.13.1513, совместима с любой платформой 8.3, которая поддерживает БСП 3.0 и старше)
Предупреждение. Нельзя использовать реквизиты и табличные части внешней обработке в процедурах/функциях, выполняемых в фоне. Данные реквизиты должны быть переданы непосредственно в вызываемую процедуру/функцию из модуля формы.
«капнуть» -> «копнуть»
(2) «не грамотный» -> «неграмотный»
Но теперь-то грамотный! А грамотность — это первое впечатление! И отсутствие подсознательного раздражения от читаемого текста.
…
Я забыл что оказывается здесь нельзя почистить комменты. Ну тогда сорри, в другой раз в личку напишу)
(3) Мне гораздо больше нравится мысль, что подобное еще никто не делал (если даже и сделал, то не говорит об этом).
(3)
«Неграмотный» или «не грамотный»: слитно или раздельно?
Если коротко, то пишется слитно, когда утверждается безграмотность, и пишется раздельно, когда отрицается грамотность.
Он неграмотный. (Утверждается безграмотность).
Он не грамотный. (Отрицается грамотность).
(Этот принцип действует и для наречия «неграмотно»).
Спасибо. Довольно интересные трюки.
(3) Да ну, нафиг! Посмотрел твой профиль… Да ты, оказывается, флудер! Сказать только ради того, чтобы сказать?! Отличная позиция! А не хочешь сделать что-нибудь полезное? Ну, кроме того, что раздувать щеки с умным видом?!
(6) Спасибо!
(7) Зачем переходить на личности, вам скучно? За полезное на работе деньги платят, а не звёздочки в интернете. Форум — это по определению место для общения, что позволяет отвлечься. Кого первого-то на флудеразм пробило? Поправили бы свою опечатку и копали дальше,.. а не капали.
За статью спасибо, кстати. С моей помощью теперь она чуть ли не идеальна))
(9)
Ну я говорю, флудер!
Кстати, где ты здесь видишь форум? Здесь специалисты делятся знаниями, а не ищут орфографические ошибки. Теми самыми знаниями, кстати, которые кто-нибудь использует в той самой работе, за которую деньги платят. А судя по тому, что пишешь в коментах, тебе еще очень далеко до такого уровня… Поищи развлекуху где-нибудь на Фейсбуке, там таких как ты любят
(10)
— К чему эти ярлыки? Не опускайтесь до моего уровня!
— Форум написано вверху.
— Я не искал ошибок, они сами бросаются в глаза и сбивают восприятие.
— За знания я никогда не устану говорить спасибо! Спасибо!
отличная статья
1. Изменились параметры процедуры «НачатьПомещениеФайлов», поэтому код процедуры «ПриОткрытии» будет таким (по крайней мере для 1С:Предприятие 8.3 (8.3.12.1685), БП 3.0):
Показать
2. Выполнения скрипта из COMОбъект(«WScript.Shell») требует особых прав и без подтверждения такого действия на сервере не работает! Соответственно, ваша обработка не отрабатывает и каждый раз вываливается запрос на подтверждение((( Можно просто поставить вместо этого цикл.
(13) Уточни, пожалуйста, что имелось в виду по п.2
(13) По п.1, тестировалось на 8.3.13.1513. Что на более ранних релизах, сказать не могу. На поздних работает
(15) Платформа тут не при чем! В последнем релизе БП 3.0 (и скорее всего и в других конфигурациях тоже!) изменился вызов команды «НачатьПомещениеФайлов»
(14) При попытке выполнить скрипт, 1с-ка стандартно спрашивает «…пытается выполнить вызов команды WScript.Shell. Подтверждаете? Да/Нет». Отвечаешь Да и по-новой вываливается этот диалог и так до посинения. Ну тебе это нужно было для «тормоза», поэтому в реальной жизни вряд ли кому-то пригодится. Так что, не заморачивайся!
(17) Точно! Фоновое задание при таком подходе запускается от имени DefUser, соответственно, COM объекты создаются только в безопасном профиле…. Ёкрныйбабай! Сам на этом споткнулся! Есть предложения по решению вопроса? (Ну, кроме того, что включать процедуру фонового задания в конфу)?
(16) Ничё не понял… При чем тут вообще БП?
Глобальный контекст (Global context)
НачатьПомещениеФайлов (BeginPuttingFiles)
Синтаксис:
НачатьПомещениеФайлов(<ОписаниеОповещенияОЗавершении>, <ПомещаемыеФайлы>, <Интерактивно>, <УникальныйИдентификаторФормы>, <ОписаниеОповещенияПередНачаломПомещенияФайлов>)
(19) Насчет БП точно — я не прав! Платформа 8.3.15.1700:
Все верно про синтаксис:
НачатьПомещениеФайлов(<ОписаниеОповещенияОЗавершении>, <ПомещаемыеФайлы>, <Интерактивно>, <УникальныйИдентификаторФормы>, <ОписаниеОповещенияПередНачаломПомещенияФайлов>)
Но у вас параметр: <ПомещаемыеФайлы> = РеквизитФормыВЗначение(«Объект»).ИспользуемоеИмяФайла (тип строка). Так не работает!
А вот как я написал:
работает..