Предисловие
Началось с того, что нужно было написать внешнюю обработку для загрузки документов в информационную базу на управляемых формах 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 Files\Java\jdk1.8.0_211\bin\javaw.exe". Это куда установлен JRE на клиентской машине.
ОбщаяСетеваяПапка - например: "\\FileServer\Public".
Код на Сервере
На Сервере создаётся временный файл в кодировке 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С весь приведён в описании, поэтому оформлять в тестовую обработку не стал. Всё равно его вставлять кусками в разные места.