简体   繁体   English

Windows 批处理文件中的增量进度条(已解决 - 请参阅我的答案)

[英]Incremental Progress Bar in Windows Batch File (RESOLVED - See my answer)

I have a batch file which scans the computer taking various readings and storing each in to a variable.我有一个批处理文件,它扫描计算机,获取各种读数并将每个读数存储到一个变量中。 During this time I would like a little more than a simple message telling the user to 'Please wait - Gathering system information'.在此期间,我想要的不仅仅是一条简单的消息,告诉用户“请稍候 - 正在收集系统信息”。

I've tried the quick, easy, (and poor), way of doing this, as follows, as I want this to be a true incremental progress bar.我已经尝试了快速、简单(而且很差)的方法,如下所示,因为我希望这是一个真正的增量进度条。

cls
echo.
echo.
echo Please wait - Gathering system information
echo ----------------------------------
echo Progress: ░░░░░░░░░░░░░░░░░░░░ 0%%
echo ----------------------------------
>nul timeout /t 1 &cls
cls

REM Do something here.

echo.
echo.
echo Please wait - Gathering system information...
echo ----------------------------------
echo Progress: █░░░░░░░░░░░░░░░░░░░ 5%%
echo ----------------------------------
>nul timeout /t 1 &cls
cls

REM Do something else here.

echo.
echo.
echo Please wait - Gathering system information.
echo ----------------------------------
echo Progress: ██░░░░░░░░░░░░░░░░░░ 10%%
echo ----------------------------------
>nul timeout /t 1 &cls
cls

REM And something else..

echo.
echo.
echo Please wait - Gathering system information..
echo ----------------------------------
echo Progress: ███░░░░░░░░░░░░░░░░░ 15%%
echo ----------------------------------
>nul timeout /t 1 &cls
cls

REM Etc...

However, the effect is not exactly great, as the cls command causes the command window to flicker, and there has to be a 'false' pause after each update, which slows the whole process… Also not great.然而,效果并不是很好,因为cls命令导致命令窗口闪烁,并且每次更新后必须有一个“假”暂停,这会减慢整个过程......也不是很好。

I have the following that looks great, but I have no idea how to 'increment' the bar after every section of code, as per my initial example, and having it play from 0-100% before running anything else is a bit pointless.我有以下看起来很棒的东西,但我不知道如何在每个代码部分之后“增加”栏,根据我最初的例子,在运行其他任何东西之前让它从 0-100% 播放有点毫无意义。

@echo off &cls
mode con: cols=70 lines=5  &color f0

call :setESC
chcp 65001 >nul

set progress=
set/a progressnum=0

:gettingdata
set progress=%progress%%ESC%[96m█%ESC%[30m
cls
echo.
echo. Please wait - Gathering system information...
echo. %progress% (%progressnum%/20)
ping localhost -n 2 >nul

set/a progressnum=%progressnum% +1
if %progressnum%==20 goto finished

goto gettingdata

:finished
echo.
echo. Finished
echo. %ESC%[92m████████████████████%ESC%[30m (20/20)
echo. Press any key to exit &>nul timeout /t -1 &exit /B


:setESC
REM Define escape char
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  set ESC=%%b
  exit /B 0
)

So, my question is, how can I get the effect of the second script, but actually increment the bar after each section of my batch script has executed?所以,我的问题是,我怎样才能获得第二个脚本的效果,但实际上在我的批处理脚本的每个部分执行后都会增加栏?

You could use ANSI codes to move the cursor, removing the need to clear the screen between updates, and move the progress bar into a function to have only one copy of the update code:您可以使用 ANSI 代码移动光标,无需在更新之间清除屏幕,并将进度条移动到一个函数中,以便只有一个更新代码的副本:

@echo off

setlocal enabledelayedexpansion
call :setESC
cls

call :progressMeter 0
echo Gathering info
timeout /t 2

call :progressMeter 33
echo Doing something else
timeout /t 2

call :progressMeter 66
echo Almost done          
timeout /t 2

call :progressMeter 100
echo All done               

goto :EOF

:progressMeter
set /a dots=%1*10/18
set /a spaces=(1000/18)-%dots%
set "dots_="
set "spaces_="
for /l %%i in (1,1,%dots%) do set "dots_=!dots_!#"
for /l %%i in (1,1,%spaces%) do set "spaces_=!spaces_! "
echo.%ESC%[1;1H[%dots_%%spaces_%] %1%%
goto :EOF

:setESC
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  set ESC=%%b
  exit /B 0
)

Ok I figured it out (with the help of this post ).好的,我想通了(在这篇文章的帮助下)。

Below is how I set up and used the script with only small additions to make it work with Unicode symbols.下面是我如何设置和使用脚本,只添加少量内容,使其与 Unicode 符号一起工作。

First, set up your environment however you please.首先,随意设置您的环境。 For the purpose of this post we will use the following:出于本文的目的,我们将使用以下内容:

@echo off &cls
mode con: cols=70 lines=4  &color f0
setlocal

Now in between each segment of your code you'll need to define the percentage of the progress bar by calling :drawProgressBar like so:现在,在代码的每个部分之间,您需要通过调用:drawProgressBar来定义进度条的百分比, :drawProgressBar

REM Your code here (segment 1)
REM - Progress Bar 0% - 33% ------------------------------------------------------
echo. Please wait - Gathering system information...
    for /l %%f in (0 1 33) do (
        call :drawProgressBar %%f "Code segment 1 finished"
    )
REM ------------------------------------------------------------------------------

Repeat as required increasing the percentage each time like so:根据需要重复每次增加百分比,如下所示:

REM Your code here (segment 2)
REM - Progress Bar 34% - 66% -----------------------------------------------------
    for /l %%f in (34 1 66) do (
        call :drawProgressBar %%f "Code segment 2 finished"
    )
REM ------------------------------------------------------------------------------
REM Your code here (segment 3)
REM - Progress Bar 67% - 100% ----------------------------------------------------
    for /l %%f in (67 1 100) do (
        call :drawProgressBar %%f "Code segment 2 finished"
    )
REM ------------------------------------------------------------------------------
REM The rest of your script goes here
endlocal
echo. &echo. All done. Press any key to Exit. &>nul timeout /t -1 &exit /B

Addendum: If you would like each segment to show 0-100% (as opposed to counting up from 0-100%) then you can use the following each time and simply update the description:附录:如果您希望每个段显示 0-100%(而不是从 0-100% 计数),那么您可以每次使用以下内容并简单地更新描述:

REM - Progress Bar 0% - 100% -----------------------------------------------------
    for /l %%f in (0 1 100) do (
            call :drawProgressBar %%f "Code segment finished"
        )
REM ------------------------------------------------------------------------------

Ok to continue and this is personal preference here, but I then like to resize the CMD Window with another cls &mode con: cols=70 lines=60 &color f0 (or whatever size and/or colour you need) then continue to the output.好的继续,这是个人喜好,但我喜欢用另一个cls &mode con: cols=70 lines=60 &color f0调整 CMD 窗口的大小cls &mode con: cols=70 lines=60 &color f0 (或您需要的任何大小和/或颜色)然后继续输出。 As I say, this is just personal choice but I think it looks better with the progress meter in a smaller windows while the information is gathered before moving on to the 'main output' of the script.正如我所说,这只是个人选择,但我认为在较小的窗口中使用进度表看起来更好,同时在转到脚本的“主要输出”之前收集信息。

Finally, add the following to the end of your batch file:最后,将以下内容添加到批处理文件的末尾:

:drawProgressBar value [text]
if "%~1"=="" goto :eof
if not defined pb.barArea call :initProgressBar
setlocal enableextensions enabledelayedexpansion
set /a "pb.value=%~1 %% 101", "pb.filled=pb.value*pb.barArea/100", "pb.dotted=pb.barArea-pb.filled", "pb.pct=1000+pb.value"
set "pb.pct=%pb.pct:~-3%"
if "%~2"=="" ( set "pb.text=" ) else ( 
    set "pb.text=%~2%pb.back%" 
    set "pb.text=!pb.text:~0,%pb.textArea%!"
)
<nul set /p "pb.prompt= !pb.fill:~0,%pb.filled%!!pb.dots:~0,%pb.dotted%! [%pb.pct%%%] %pb.text%!pb.cr!"
endlocal
goto :eof

:initProgressBar [fillChar] [dotChar]
chcp 65001 >nul
if defined pb.cr call :finalizeProgressBar
for /f %%a in ('copy "%~f0" nul /z') do set "pb.cr=%%a"
if "%~1"=="" ( set "pb.fillChar=▓" ) else ( set "pb.fillChar=%~1" )
if "%~2"=="" ( set "pb.dotChar=▒" ) else ( set "pb.dotChar=%~2" )
set "pb.console.columns="
for /f "tokens=2 skip=4" %%f in ('mode con') do if not defined pb.console.columns set "pb.console.columns=%%f"
set /a "pb.barArea=pb.console.columns/2-2", "pb.textArea=pb.barArea-9"
set "pb.fill="
setlocal enableextensions enabledelayedexpansion
for /l %%p in (1 1 %pb.barArea%) do set "pb.fill=!pb.fill!%pb.fillChar%"
set "pb.fill=!pb.fill:~0,%pb.barArea%!"
set "pb.dots=!pb.fill:%pb.fillChar%=%pb.dotChar%!"
set "pb.back=!pb.fill:~0,%pb.textArea%!
set "pb.back=!pb.back:%pb.fillChar%= !"
endlocal & set "pb.fill=%pb.fill%" & set "pb.dots=%pb.dots%" & set "pb.back=%pb.back%"
chcp 1252 >nul
goto :eof

:finalizeProgressBar [erase]
if defined pb.cr (
    if not "%~1"=="" (
        setlocal enabledelayedexpansion
        set "pb.back="
        for /l %%p in (1 1 %pb.console.columns%) do set "pb.back=!pb.back! "
        <nul set /p "pb.prompt=!pb.cr!!pb.back:~1!!pb.cr!"
        endlocal
    )
)
for /f "tokens=1 delims==" %%v in ('set pb.') do set "%%v="
goto :eof

This is probably an easy task for the seasoned guys & gals here but I struggled with how to do this so I thought that I would share what worked for me and how I used the script.对于这里的经验丰富的男士和女士来说,这可能是一项简单的任务,但我很难做到这一点,所以我想我会分享对我有用的内容以及我如何使用脚本。

Full credit goes to MC ND who is the original author of the script used.全部归功于MC ND ,他是所用脚本的原作者。 Please see the original post for more customisation options.有关更多自定义选项,请参阅原始帖子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM