[CMD] progress bar

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
188
доброго времени суток! захотелось сделать что-то наподобие прогресс бара во время выполнения батника (установка софта) ...

на коленке нарисовал такое:

CMD/BATCH:
@echo off

:begin
cls
set "per= ^[^----------^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^>---------^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^-^>--------^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^--^>-------^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^---^>------^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^----^>-----^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^-----^>----^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^------^>---^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^-------^>--^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^--------^>-^] "
echo %per%
timeout /t 2 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
cls
set "per= ^[^---------^>^] "
echo %per%
timeout /t 2 /nobreak >nul
goto begin
:exit

exit /b

даже работает))

скриптик проверяет появление текстового файла (который должен появиться после завершения установки софта)

но.. мне бы хотелось поместить прогресс-бар в батник так, чтобы помимо самого прогресс бара еще инфа отображалась для юзеров... типа такого:

CMD/BATCH:
echo.
echo    Unity installer:
echo    ================
echo.
echo.
echo    Installation of Unity version %vers% has been started
echo.
echo.
echo.   Please do not close the application before the end of the installation
echo.
echo.
echo.
echo.
:: вот куда-нибудь в это место хотелось бы поместить прогресс-бар..
echo.

но как это сделать? не перерисовывать же каждый раз полностью все это... иначе простыня получится да и не круто это... можно что-нибудь покрасивше и получше придумать? может с циклами что-то? я мало что в них понимаю...
буду рад помощи. может кому-то тоже такая штука интересна...
 

Кирилл

Команда форума
Администратор
Сообщения
14,102
Реакции
6,152
Баллы
993
Ну вызовите его через call?
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
188
вроде разобрался.
сделал так:

CMD/BATCH:
@ECHO OFF
SetLocal EnableExtensions

set num=1

:begin
call :progressbar %num%
cls
echo.
echo    Unity installer:
echo    ================
echo.
echo.
echo    Installation of Unity version %vers% has been started
echo.
echo.
echo.   Please do not close the application before the end of the installation
echo.
echo.
echo.
echo.  %progressbar%
timeout /t 1 /nobreak >nul
if exist c:\temp\unity_log.txt goto exit
set /a num=%num%+1
if %num% == 50 set num=1
goto begin

:progressbar

goto progress%1

:progress1
set "progressbar= ^[ ---------------------------------------- ^] "
exit /b

:progress2
set "progressbar= ^[ ^>--------------------------------------- ^] "
exit /b

:progress3
set "progressbar= ^[ -^>-------------------------------------- ^] "
exit /b

:progress4
set "progressbar= ^[ --^>------------------------------------- ^] "
exit /b

:progress5
set "progressbar= ^[ ---^>------------------------------------ ^] "
exit /b

:progress6
set "progressbar= ^[ ---^>------------------------------------ ^] "
exit /b

:: ...
:: ...
:: ...
:: ...
:progress50
set "progressbar= ^[ ---------------------------------------^> ^] "
exit /b[/code]


все работает, но слишком уж громоздкий код получается... возможно это как-то попроще сделать и покрасивше? мб через цикл или еще как-то... ?
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
188
пожалуй, все это не имеет смысла... ибо пока выполняется этот код, другой (в частности основная задача - установка софта) выполняться не будет.. :This:
 

Кирилл

Команда форума
Администратор
Сообщения
14,102
Реакции
6,152
Баллы
993
Так вы параллельно запускайте
 

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,403
Реакции
5,907
Баллы
718
Пример:

CMD/BATCH:
@echo off
SetLocal EnableExtensions

if "%~1"=="ProgressBar" (call :ProgressBarEx& exit)

echo.
echo.
echo.
echo My Program
echo.
echo Begin LONG LONG operation

call :ProgressBar Start

ping 127.1 -n 10

call :ProgressBar Stop

echo.
echo Finished.
pause>NUL
goto :eof


:ProgressBar [Start/Stop]
  if /i "%~1"=="Stop" (del "RegBack.reg"& exit /B)
  >nul reg export "HKCU\Console" RegBack.reg /y
  >nul reg add "HKCU\Console\%%SystemRoot%%_system32_cmd.exe" /v "ScreenBufferSize" /t REG_DWORD /d 0x1001e /f
  >nul reg add "HKCU\Console\%%SystemRoot%%_system32_cmd.exe" /v "WindowSize" /t REG_DWORD /d 0x1001e /f
  start cmd /k "%~f0" ProgressBar
Exit /B

:ProgressBarEx
  >nul 2>&1 reg import "RegBack.reg"
  title Ожидайте ...
  For /L %%C in (1,1,2147483647) do (
    ping 127.1 -n 1 >nul
    ping 127.1 -n 1 >nul
    if not exist "RegBack.reg" exit
    set /p="|"<NUL
  )
exit /B

Screenshot_1.png


Вместо ping 127.1 -n 10 подставляете полезную нагрузку.
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
188

здорово! но хотелось бы обойтись одним окошком...
Так вы параллельно запускайте

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

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,403
Реакции
5,907
Баллы
718

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,403
Реакции
5,907
Баллы
718
В принципе можно заменить синхронное ожидание процесса на асинхронное, но это будет сильно нагружать ЦП.
Как вариант, взять в качестве признака проверку на создание какого-то файла, но это будет весьма ненадёжно и не универсально, т.к. в следующей версии установщик например больше не будет создавать отслеживаемый файл и придётся снова корректировать этот скрипт прогрессбара.
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
188
так я так и сделал. с проверкой на наличие файла. т.е. после отработки основного кода скрипта создается скажем, log.txt
т.е. файл есть - работу прогресс-бара прекращаем. насчет неуниверсальности - думаю ничего сложного нет сделать при запуске скрипта проверку на наличие этого файла. если есть - прибиваем.
 

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,403
Реакции
5,907
Баллы
718
Я думаю, что вы не совсем правильно меня поняли.
log.txt (или какой-то другой файл) должен создать не ваш скрипт, а установщик*, чтобы служить опознавательным моментом времени того, что он завершил свою работу и можно прекращать крутить по кругу прогрессбар и начать заниматься другими делами.

* под установщиком подразумевается отдельный процесс, а не какой-нибудь call внутри батника.

Или как вариант, проверять наличие процесса, но это сожрёт процессорное время.
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
188
Я думаю, что вы не совсем правильно меня поняли.
log.txt (или какой-то другой файл) должен создать не ваш скрипт, а установщик*, чтобы служить опознавательным моментом времени того, что он завершил свою работу и можно прекращать крутить по кругу прогрессбар и начать заниматься другими делами.

* под установщиком подразумевается отдельный процесс, а не какой-нибудь call внутри батника.

Или как вариант, проверять наличие процесса, но это сожрёт процессорное время.

разве нельзя через errorlevel ?
 

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,403
Реакции
5,907
Баллы
718
В cmd по errorlevel можно только, если синхронно, только для консольных процессов и только если это предусмотрено разработчиком программы.
В Вашем случае ничего ничего из этого не будет соблюдено.

А вообще, да. В WinApi так и делают - смотрят код возврата, имея на руках ProcessID запущенного процесса. Если он = STILL_ALIVE, то процесс ещё жив.
 
Последнее редактирование:

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
188
В cmd по errorlevel можно только, если синхронно, только для консольных процессов и только если это предусмотрено разработчиком программы.
В Вашем случае ничего ничего из этого не будет соблюдено.

А вообще, да. В WinApi так и делают - смотрят код возврата, имея на руках ProcessID запущенного процесса. Если он = STILL_ALIVE, то процесс ещё жив.

я имел ввиду что-то типа такого:

Код:
\\server\Soft\Developers_Tools\Unity\4_5_1\f3\UnitySetup-4.5.1.exe /S /D=C:\Program Files (x86)\Unity_4.5.1
if %ERRORLEVEL%==1 (echo installation error >c:\temp\unity_error_log.txt) else echo installation finished >c:\temp\unity_log.txt

т.е. если errorlevel 0 - считаем, что процесс выполнен успешно и создаем соответствующий файл. если 1 - значит ошибка.
ну а скрипт с прогресс-баром соответственно ждет появления того или другого файла и после их появления прекращает
крутиться, выводя соответсвующее сообщение: либо успех установки, либо что-то пошло не так.

т.е. в данном случае любой код возврата означает завершение работы, независимо - успешно или нет. соответственно на основании этого можно создать файл.


что плохого в данной реализации?
 
Последнее редактирование:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,403
Реакции
5,907
Баллы
718
что плохого в данной реализации?
То, что он не соответствует Вашему требованию, чтобы было не больше 1 окна. Если первое будет ждать завершения процесса, как выполнить код прогрессбара, не имея второго окна (процесса)?
cmd не поддерживает создание потоков.
 
Сверху Снизу