首页 > 解决方案 > Windows 批处理文件中的增量进度条

问题描述

我有一个批处理文件,它扫描计算机以获取各种读数并将每个读数存储到一个变量中。在此期间,我想要的不仅仅是一条简单的消息,告诉用户“请稍候 - 正在收集系统信息”。

我已经尝试了快速、简单(但很差)的方法,如下所示,因为我希望这是一个真正的增量进度条。

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...

但是,效果并不是特别好,因为cls命令会导致命令窗口闪烁,并且每次更新后都必须有一个“错误”的暂停,这会减慢整个过程……也不是很好。

我有以下看起来很棒,但我不知道如何在每个代码部分之后“增加”栏,根据我最初的示例,并且在运行其他任何内容之前让它从 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
)

所以,我的问题是,我怎样才能得到第二个脚本的效果,但在我的批处理脚本的每个部分执行后实际上增加了条形?

标签: windowsbatch-file

解决方案


好的,我想通了(在这篇文章的帮助下)。

下面是我如何设置和使用脚本,只添加少量内容,使其与 Unicode 符号一起使用。

首先,随心所欲地设置环境。出于本文的目的,我们将使用以下内容:

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

现在,在代码的每个部分之间,您需要通过如下调用来定义进度条的百分比: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 ------------------------------------------------------------------------------

根据需要重复每次增加百分比,如下所示:

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

附录:如果您希望每个段显示 0-100%(而不是从总体上从 0-100% 开始计数),那么您可以每次使用以下内容并简单地更新描述:

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

好的继续,这是个人喜好,但我想用另一个cls &mode con: cols=70 lines=60 &color f0(或你需要的任何大小和/或颜色)调整 CMD 窗口的大小,然后继续输出。正如我所说,这只是个人选择,但我认为在较小的窗口中使用进度表看起来会更好,同时在移动到脚本的“主要输出”之前收集信息。

最后,将以下内容添加到批处理文件的末尾:

: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=▓&quot; ) else ( set "pb.fillChar=%~1" )
if "%~2"=="" ( set "pb.dotChar=▒&quot; ) 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

对于这里经验丰富的男士和女士来说,这可能是一项容易的任务,但我为如何做到这一点而苦苦挣扎,所以我想我会分享对我有用的东西以及我如何使用脚本。

完全归功于MC ND,他是所用脚本的原作者。有关更多自定义选项,请参阅原始帖子。


推荐阅读