Индикатор выполнения длительных операций на сервере 1С 8.3 (управляемые формы)




Индикатор выполнения (отображение прогресса) длительных операций в тонком клиенте 1С:Предприятия 8.3, когда полностью весь код исполняется на сервере, а клиент просто ждёт завершения. Используются внешние средства (либо командное окно Windows, либо приложение Java).

Предисловие

Началось с того, что нужно было написать внешнюю обработку для загрузки документов в информационную базу на управляемых формах 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С весь приведён в описании, поэтому оформлять в тестовую обработку не стал. Всё равно его вставлять кусками в разные места.

20 Comments

  1. VmvLer

    слишком сложно, слишком много если и слишком дорого.

    картинка с прогресс-баром с меркетинговой точки зрения логична, но на реальных базах будет красива только при обходе коллекций —

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

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

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

    Reply
  2. D.B.Sokolov

    (1) У меня как раз пользователи этим занимаются. Это применяется в обработке, которая загружает в базу кучу документов из другой программы.Колесо и котик как раз не работают. т.к. процедуры обработки запускаются не в фоне. Колесо не крутится, кот не шевелится.

    Reply
  3. D.B.Sokolov

    (1) Скинул цену до 1 $m.

    Reply
  4. Serj1C

    Спасибо за идею. Реализовал в своем проекте (на базе cmd)

    Reply
  5. Xershi

    (2) переписать на внешнюю обработку. Там и котик и прогресс есть и доп текст тоже! На ИС уже появилась толковая статья, проверял у себя все работает с БСП 2.3.

    Reply
  6. Serj1C

    (4) пришлось изрядно повозиться, чтобы победить проблему кодировок

    Reply
  7. D.B.Sokolov

    (5)

    На ИС уже появилась толковая статья

    Ссылочку бы на статью…

    Reply
  8. Xershi

    (7) добавил в избранное, ловите

    https://infostart.ru/public/1058914/

    Reply
  9. D.B.Sokolov

    (6) Если писать в КодировкаТекста.OEM, то и проблем, вроде, не должно быть.

    Reply
  10. D.B.Sokolov

    (8) Спасибо, поизучаю.

    Reply
  11. lazarenko

    Система оповещения решает эту задачу

    Reply
  12. D.B.Sokolov

    (11) В смысле, «Система взаимодействия» или что-то другое имеете в виду?

    Reply
  13. lazarenko

    (12) да, она самая

    Reply
  14. herfis

    Или я чего-то не понял, или задача решается без лишних приблуд.

    Еще 5 лет назад рисовал: https://infostart.ru/public/274721/

    Reply
  15. D.B.Sokolov

    (14) Сначала показалось, что это большие дебри. Вместо того, чтобы влезать в них, решил, что проще писать в TXT и читать оттуда. К тому же БСП постоянно меняется (неожиданно), и зависеть от неё не хотелось.

    Потом подумал, что прикольно будет написать на Java. Родилась вот такая идея.

    Ещё видел у кого-то вариант, писать в HTML-файл с параметром автообновления страницы. Но запускать целый браузер ради индикации, не очень как-то.

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

    Reply
  16. independ
  17. D.B.Sokolov
  18. independ

    (17) да кстати, пробовал, работает

    Reply
  19. independ

    (17) в этом варианте вместо html можно использовать hta

    http://forum.infostart.ru/forum9/topic124115/message2229301/#message2229301

    Reply
  20. herfis

    (15)

    К тому же БСП постоянно меняется (неожиданно), и зависеть от неё не хотелось.

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

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

    Но тащить внешние зависимости и жертвовать переносимостью ради прогресс-бара — это эребор для продуктового решения.

    В качестве задачки для самообучения с уклоном в смежные технологии — понять могу.

    Reply

Leave a Comment

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