Индикатор выполнения длительных операций на сервере 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 не будет опубликован. Обязательные поля помечены *