Предисловие
Началось с того, что нужно было написать внешнюю обработку для загрузки документов в информационную базу на управляемых формах 1С 8.3. Конфигурация типовая без возможности изменения. Поскольку с запуском процедур из модуля внешней обработки в фоновом режиме не так всё просто, пришлось изобретать способ индикации пользователю процента выполнения операций.
Как это работает у меня
Реализовал два варианта.
Первый работает в командном окне Windows. По сути это командный файл, который в процессе работы добавляет строки в консоль. Не очень красиво. Зато просто и работает везде. В архиве это файл progress.cmd.
Второй вариант — это Java-приложение для Java 8 (JRE 1.8). Красивое маленькое окно с прогресс-баром. Нужно устанавливать виртуальную машину Java. В архиве это файл ProgressBar.jar.
Описание
В локальной сети имеем общую сетевую папку с правами на чтение и запись как со стороны Клиента, так и со стороны Сервера. Туда кладём нашу внешнюю программу индикации (progress.cmd или ProgressBar.jar, или оба варианта). Там же будут создаваться временные файлы. Сервер будет создавать файлы и писать в них. Программа с клиентской машины будет читать файлы и затем удалять их.
На клиенте, перед запуском длительной операции, генерируется уникальное имя файла для передачи его на Сервер и в нашу программку. После этого на Клиенте запускается внешнее приложение для индикации, куда в качестве параметра передаётся это имя файла. И уже после этого вызывается серверная процедура, с именем файла в параметрах.
Клиент 1С, скажем так, "подвисает", ожидая завершения операции. Но наша программулина работает и отображается поверх окна 1С.
Код на Клиенте:
Если ПоказыватьПроцентВыполнения И ЗначениеЗаполнено(ОбщаяСетеваяПапка) Тогда
Если СпособИндикации = 0 Тогда
ПрограммаИндикации = ОбщаяСетеваяПапка + ?(Прав(ОбщаяСетеваяПапка, 1) = "", "", "") + "progress.cmd";
ФайлПрограммы = Новый Файл(ПрограммаИндикации);
Если ФайлПрограммы.Существует() Тогда
УникальноеИмяФайла = Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss") + "_" + Строка(Новый УникальныйИдентификатор) + ".txt";
ИмяФайлаИндикации = ОбщаяСетеваяПапка + ?(Прав(ОбщаяСетеваяПапка, 1) = "", "", "") + УникальноеИмяФайла;
СтруктураПараметров.Вставить("ИмяФайлаИндикации", ИмяФайлаИндикации);
ЗапуститьПриложение(ПрограммаИндикации + " " + ИмяФайлаИндикации);
КонецЕсли;
ФайлПрограммы = Неопределено;
Иначе
ПрограммаИндикации = ОбщаяСетеваяПапка + ?(Прав(ОбщаяСетеваяПапка, 1) = "", "", "") + "ProgressBar.jar";
ФайлJava = Новый Файл(ПутьКJava);
ФайлПрограммы = Новый Файл(ПрограммаИндикации);
Если ФайлJava.Существует() И ФайлПрограммы.Существует() Тогда
УникальноеИмяФайла = Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss") + "_" + Строка(Новый УникальныйИдентификатор) + ".txt";
ИмяФайлаИндикации = ОбщаяСетеваяПапка + ?(Прав(ОбщаяСетеваяПапка, 1) = "", "", "") + УникальноеИмяФайла;
СтруктураПараметров.Вставить("ИмяФайлаИндикации", ИмяФайлаИндикации);
ЗапуститьПриложение(ПутьКJava + " -jar " + ПрограммаИндикации + " " + ИмяФайлаИндикации);
КонецЕсли;
ФайлJava = Неопределено;
ФайлПрограммы = Неопределено;
КонецЕсли;
КонецЕсли;
ЗагрузитьДокументыСервер(СтруктураПараметров);
ПутьКJava должен содержать что-то вроде "c:Program FilesJavajdk1.8.0_211injavaw.exe". Это куда установлен JRE на клиентской машине.
ОбщаяСетеваяПапка — например: "\FileServerPublic".
Код на Сервере
На Сервере создаётся временный файл в кодировке DOS (OEM).
Если ЗначениеЗаполнено(СтруктураПараметров.ИмяФайлаИндикации) Тогда
ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.ДобавитьСтроку("Начало чтения файлов");
Попытка
ТекстДок.Записать(СтруктураПараметров.ИмяФайлаИндикации, КодировкаТекста.OEM);
Исключение
КонецПопытки;
КонецЕсли;
По мере работы процедуры в ПЕРВУЮ строку файла будем писать текущий процент выполнения в виде: 25,0%. Здесь важно поставить знак процента после числа, а перед числом ничего не должно быть, т.е. оно стоит вначале строки. Также можно записывать некоторые короткие информационные сообщения в одну строку.
Индикатор = Индикатор + 1;
Если Индикатор > 0 И Индикатор % 100 = 0 Тогда
ТекстДок.Очистить();
ТекстДок.ДобавитьСтроку(?(ВсегоСтрок = 0, "ожидайте", Формат(Индикатор * 100 / ВсегоСтрок, "ЧДЦ=1; ЧГ=0") + "%"));
Попытка
ТекстДок.Записать(ПараметрыСервер.ИмяФайлаИндикации, КодировкаТекста.OEM);
Исключение
КонецПопытки;
КонецЕсли;
Когда Сервер завершит все свои дела, во временный файл записываем служебное слово "stop". Это будет сигналом к закрытию программы индикации.
ТекстДок.Очистить();
ТекстДок.ДобавитьСтроку("stop");
Попытка
ТекстДок.Записать(СтруктураПараметров.ИмяФайлаИндикации, КодировкаТекста.OEM);
Исключение
КонецПопытки;
ТекстДок = Неопределено;
Что делает программа индикации. Она через каждые 5 секунд читает временный файл и выводит то, что содержится в первой строке. Вариант с Java при этом преобразовывает считанное в число и показывает прогресс-бар. Как только программа встречает "stop", удаляет временный файл и закрывается.
Надо добавить ещё вот что. Пользователь может раньше времени закрыть программу индикации. Тогда временный файл не будет удалён. Поэтому на Клиенте надо по завершении проверить, не осталось ли чего, и удалить мусор.
P.S. Для скачивания выкладываю только внешние приложения *.cmd и *.jar. Код для 1С весь приведён в описании, поэтому оформлять в тестовую обработку не стал. Всё равно его вставлять кусками в разные места.
слишком сложно, слишком много если и слишком дорого.
картинка с прогресс-баром с меркетинговой точки зрения логична, но на реальных базах будет красива только при обходе коллекций —
такие задачи редки и выполняться опытными разработчиками, которым на красоту класть.
пользователям да, красота и удобство важны, но как правило они работают не с коллекциями, а с отчетами и обработками и никого прогресса там не будет.
посему колесико и котик из БСП лично меня устраивает больше чем масса сомнительно кода с вагоном требований и ограничений.
(1) У меня как раз пользователи этим занимаются. Это применяется в обработке, которая загружает в базу кучу документов из другой программы.Колесо и котик как раз не работают. т.к. процедуры обработки запускаются не в фоне. Колесо не крутится, кот не шевелится.
(1) Скинул цену до 1 $m.
Спасибо за идею. Реализовал в своем проекте (на базе cmd)
(2) переписать на внешнюю обработку. Там и котик и прогресс есть и доп текст тоже! На ИС уже появилась толковая статья, проверял у себя все работает с БСП 2.3.
(4) пришлось изрядно повозиться, чтобы победить проблему кодировок
(5)
Ссылочку бы на статью…
(7) добавил в избранное, ловите
https://infostart.ru/public/1058914/
(6) Если писать в КодировкаТекста.OEM, то и проблем, вроде, не должно быть.
(8) Спасибо, поизучаю.
Система оповещения решает эту задачу
(11) В смысле, «Система взаимодействия» или что-то другое имеете в виду?
(12) да, она самая
Или я чего-то не понял, или задача решается без лишних приблуд.
https://infostart.ru/public/274721/
Еще 5 лет назад рисовал:
(14) Сначала показалось, что это большие дебри. Вместо того, чтобы влезать в них, решил, что проще писать в TXT и читать оттуда. К тому же БСП постоянно меняется (неожиданно), и зависеть от неё не хотелось.
Потом подумал, что прикольно будет написать на Java. Родилась вот такая идея.
Ещё видел у кого-то вариант, писать в HTML-файл с параметром автообновления страницы. Но запускать целый браузер ради индикации, не очень как-то.
Но теперь всё-таки решил, что надо будет разобраться в стандартных механизмах. Наверное, оно того стоит.
(16) Вот ещё:https://infostart.ru/public/326393/
(17) да кстати, пробовал, работает
(17) в этом варианте вместо html можно использовать hta
http://forum.infostart.ru/forum9/topic124115/message2229301/#message2229301
(15)
Поэтому обжегшись пару раз, я постарался свести зависимости к разумному минимуму.
К сожалению, полностью универсально сделать невозможно, так как для запуска в фоне процедуры внешней обработки необходима как минимум функция общего модуля, умеющая запускать произвольный код. В БСП она хоть стандартная.
Но тащить внешние зависимости и жертвовать переносимостью ради прогресс-бара — это эребор для продуктового решения.
В качестве задачки для самообучения с уклоном в смежные технологии — понять могу.