progress bar while doing command

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
AR Coding
Posts: 17
Joined: 02 May 2021 21:16

progress bar while doing command

#1 Post by AR Coding » 31 May 2021 15:15

Hi, ive seen this, viewtopic.php?p=17719#p17719 but is there a way to make a progress bar with any command, while the command is running? I dont know where to put the code. Maybe someone can make something like:

Code: Select all

call :progbar "command"
But i would appreciate anything that works.

Thank you!
Last edited by AR Coding on 31 May 2021 22:25, edited 1 time in total.

T3RRY
Posts: 158
Joined: 06 May 2020 10:14

Re: progress bar while doing command

#2 Post by T3RRY » 31 May 2021 21:42

AR Coding wrote:
31 May 2021 15:15
Hi, ive seen this, viewtopic.php?p=17719#p17719 but is there a way to make a progress bar with any command? I dont know where to put the code. Maybe someone can make something like:

Code: Select all

call :progbar "command"
But i would appreciate anything that works.

Thank you!
I don't see it as being practical or possible to make a progress bar for any command, as each commands execution time is essentially unknown.
As such, no meaningful representation can be made of how long a given command has left before completion.
It would be much simpler to display an in progress animation through the use of a 2nd thread that is started before a given command and stopped after said command.

AR Coding
Posts: 17
Joined: 02 May 2021 21:16

Re: progress bar while doing command

#3 Post by AR Coding » 31 May 2021 21:59

T3RRY wrote: It would be much simpler to display an in progress animation through the use of a 2nd thread that is started before a given command and stopped after said command.
@T3RRY - thanks for the fast reply.
can you please give me an example of how to do that?

T3RRY
Posts: 158
Joined: 06 May 2020 10:14

Re: progress bar while doing command

#4 Post by T3RRY » 01 Jun 2021 10:29

AR Coding wrote:
31 May 2021 21:59
T3RRY wrote: It would be much simpler to display an in progress animation through the use of a 2nd thread that is started before a given command and stopped after said command.
@T3RRY - thanks for the fast reply.
can you please give me an example of how to do that?
A barebones example, that should give you a good starting point:

Code: Select all

@Echo off
 If not "%~1" == "" Goto %1
 Cls
:# macros for launch and termination of 2nd thread via start / stop flag written to alternate data stream.
 Set "Start.Thread.2=(Powershell -c "remove-item -path '%~nx0' -Stream 'Status'") 2> nul & Echo(Loading&((Echo(1)>"%~f0:Status") & Start /b "" "%~f0" Thread2"
 Set "End.Thread.2=((Echo(0)>"%~f0:Status")&Echo("

 %Start.Thread.2%
 For /l %%i in (1 1 200000)Do Set var=%%i
 %End.Thread.2%
 Echo(%var%

 Pause
Goto :Eof

:Thread2
:# Check completion status flagged in status stream of this file. Exit on 0 flag [stopped].
 (More < "%~f0:Status" 2> nul) | findstr /LIC:"0" > nul && Exit
:# Basic animation. modify to suit your needs.
 <nul Set /p "=."
:# Subsecond delay. ~ 1/60th of a second
 For /L %%i in (1 1 800)Do (
  (Call )
 )
Goto :Thread2

AR Coding
Posts: 17
Joined: 02 May 2021 21:16

Re: progress bar while doing command

#5 Post by AR Coding » 01 Jun 2021 18:13

Thanks for the script! Ill try it when i get a chance.
Where should i put my command for the bar?

T3RRY
Posts: 158
Joined: 06 May 2020 10:14

Re: progress bar while doing command

#6 Post by T3RRY » 02 Jun 2021 03:40

AR Coding wrote:
01 Jun 2021 18:13
Thanks for the script! Ill try it when i get a chance.
Where should i put my command for the bar?
animation is actioned in

Code: Select all

:thread2
Note the remark regarding the use of

Code: Select all

<nul set /p "=."
to output an additional period each time the loop iterates.
It is the simplest animation to action. replace with a scripted animation to suit your needs as indicated in this section of the script:

Code: Select all

:# Basic animation. modify to suit your needs.
 <nul Set /p "=."
Notes:
  • If the command you are executing while thread 2 is active outputs to the con device, the above form of animation will cease to output on a single line, instead it will be intermingled with the output of the command.
    If the execution time of the command is too short, the animation will not have time to be output
A example of modifying the above to achieve a more complex animation [Note VT usage requires windows 10 v1909 or higher]:

Code: Select all

@Echo off
:# Used to jump to Thread2 on relaunch
 If /I "%~1" == "Thread2" Goto %1
 Cls

:# Define Escape character for Virtual terminal sequences 
For /f "Delims=" %%e in ('Echo(Prompt $E^|Cmd')Do Set "\E=%%e"

:# macros for launch and termination of 2nd thread via start / stop flag written to alternate data stream.
:#------------------
:# Start.Thread.2 - Remove status thread from this file if present;
:#                  Notify command has started;
:#                  Flag status 1 in Stream :status;
:#                  Use start /b with params to relaunch this script and execute second thread

 Set "Start.Thread.2=(Powershell -c "remove-item -path '%~nx0' -Stream 'Status'") 2> nul & Echo(Executing&((Echo(1)>"%~f0:Status") & Start /high /b "" "%~f0" Thread2"
:#------------------
:# End.Thread.2   - Flag status 0 in Stream :Status;
:#                  Execute a small delay to ensure thread two has time to emit linefeed and enable cursor display.
 Set "End.Thread.2=((Echo(0)>"%~f0:Status")&For /L %%i in (1 1 750)Do ((Call ))"
 Mode 160
 For /f "Tokens=2 delims=: " %%G in ('Mode^|findstr /lic:"Columns"')Do Set "Columns=%%G"

 %Start.Thread.2% + 200
 For /l %%i in (1 1 200000)Do Set var=%%i
 %End.Thread.2%
 Echo([%var%] iterations actioned.

 Pause
Goto :Eof

:Thread2
 If not "%~3" == "" ( Set "Delay[i]=%~3" )Else Set "Delay[i]=800"
 <nul Set /p "=%\E%7%\E%[?25l"
 Set "T2[i]=0"
 Set "T2[c]=160"
:T2.Loop
Set /A T2[i]+=1,T2[c]+=1
:# Check completion status flagged in status stream of this file.
 (More < "%~f0:Status" 2> nul) | findstr /LIC:"0" > nul && (<nul Set /P "=%\E%[?25h%\E%[1E"& Exit)
:# Basic animation. modify to suit your needs.
 <nul Set /p "=%\E%8%\E%[3%T2[i]%m%~2%\E%[0m%\E%7"
 If %T2[i]% EQU 7 Set "T2[i]=0"
 If %T2[c]% GEQ %Columns% (Set "T2[c]=0" & <nul Set /P "=%\E%[1G%\E%7%\E%[K")

Goto :T2.Loop

AR Coding
Posts: 17
Joined: 02 May 2021 21:16

Re: progress bar while doing command

#7 Post by AR Coding » 02 Jun 2021 08:16

What does the + 200 do in

Code: Select all

%Start.Thread.2% + 200
Sorry if im asking to many questions , im just not very good at this :(

T3RRY
Posts: 158
Joined: 06 May 2020 10:14

Re: progress bar while doing command

#8 Post by T3RRY » 02 Jun 2021 08:36

AR Coding wrote:
02 Jun 2021 08:16
What does the + 200 do in

Code: Select all

%Start.Thread.2% + 200
Sorry if im asking to many questions , im just not very good at this :(
the '+' is the character output r the loading bar, the '200' is redundant from an alternate version that took a numeric parameter to base a delay on.
as this version clears the line once full, that delay is no longer necessary.

An expanded version which tests support for Virtual terminal sequences and alternate data streams, and uses a RGB spinner bar for the animation:

Code: Select all

:# Author: T3RRY Created: 03/06/2021
:# Purpose: RGB Spinner animation for load / waiting indication while script continues to run.
:# Utilises a second thread to display animation while the main script continues executing.
:# Execution and termination of the thread is controlled using a value stored in an alternate data
:# stream of this file:. 1 = run ; 0 = stop

@Echo off & CD /D "%~dp0"
======:# Runs Thread on relaunch
 If /I "%~1" == "Thread" Goto %1
 Cls

====================:# OS Requirement tests
:# Verify NTFS drive
 (Echo(verify.NTFS >"%~f0:Status") || (Echo(This file must be located on an NTFS drive as it utilises alternate data streams.&Exit /B 1)

=========================:# Windows Version control.
 Set "Win10="
 Ver | Findstr /LIC:" 10." > nul && Set "Win10=true"

============================:# Test if virtual terminal codes enabled ; enable if false
:# removes win10 flag definition if version does not support Virtual Terminal sequences
 If defined Win10 (
  Reg Query HKCU\Console | %SystemRoot%\System32\findstr.exe /LIC:"VirtualTerminalLevel    REG_DWORD    0x1" > nul || (
    Reg Add HKCU\Console /f /v VirtualTerminalLevel /t REG_DWORD /d 1
  ) > Nul || Set "Win10="
 )
 If not defined Win10 (
  Echo(Virtual terminal sequences not supported on your system
  Exit /B 1
 )

=====:# Define Escape character for Virtual terminal sequences 
For /f "Delims=" %%e in ('Echo(Prompt $E^|Cmd')Do Set "\E=%%e"

==================:# macros start and stop Thread via t/f flag written to alternate data stream.
:# Start.Thread - Save current Codepage;
:#                Remove status thread from this file if present;
:#                Notify command has started;
:#                Flag status 1 in Stream :status;
:#                Use start /b with params to relaunch this script and execute second thread
 Set "Start.Thread=(For /F "tokens=2 Delims=:" %%G in ('CHCP')Do Set "restore.CP=CHCP %%G")&((Echo(1)>"%~f0:Stream") & Start /AboveNormal /b "executing." "%~f0" Thread"

:# End.Thread  - Flag status 0 in Stream :Status;
:#               Execute a small delay to ensure thread two has time to enable cursor display and clear animation.
:#               [Delay of approx. 1/66th of a second]
 Set "End.Thread=((Echo(0)>"%~f0:Stream")&For /L %%i in (1 1 750)Do ((Call ))"

===:# Usage Examples. Multiple examples used to show thread is suitable for use with
   :# commands of any execution time.
   :# Example of running RGB spinner animation while another command executes.
   :# NOTE: Commands with output must be redirected to a stream or file
   :#       and output using more or type AFTER using the End.Thread macro
   :#       as the spinner animation moves the cursor and console output that
   :#       occurs during spinner animation will displace and be displaced by the animation.
               
 %Start.Thread% Example 1
  For /l %%i in (1 1 100000)Do Set "var=%%i"
 %End.Thread%
 Echo([%var%] iterations actioned.

 %Start.Thread% Example 2
  For /l %%i in (1 1 10000)Do Set "var=%%i"
 %End.Thread%
 Echo([%var%] iterations actioned.

 %Start.Thread% Example 3
 Set "var=1"
 %End.Thread%
 Echo([%var%] iterations actioned.

======================================:# End script cleanup
 Powershell -c "remove-item -path '%~nx0' -Stream '*'"
 @Pause

Goto :Eof

===========================================================
:Thread - Animation; RGB spinner
:# NOTE - Multiple instances of this thread can not be run in parallel;
:#        as Virtual terminal Cursor save operation will overide information stored by parallel threads

 Set ^"Params=%*"
 Setlocal EnableDelayedExpansion
 Set "Params=!Params:%~1 =!"
 TITLE !Params!
 CHCP 65001 > nul
 <nul set /p "=%\E%[1EExecuting:%\E%[36m !Params!%\E%[0m%\E%[?25l%\E%[1E%\E%7"

 Set "T2[L]=0"         %= Rem Spinner Loop count    =%
 Set "T2[chars]= |/-\" %= Rem Spinner characters    =%
 Set "Delay=5"         %= Framerate in Centiseconds =%

:# frame control via elapsed time by Dave Benham - https://www.dostips.com/forum/viewtopic.php?f=3&t=4741

 For /l %%. in ()Do (
  %= Check completion status flagged in status stream of this file; =%
  (For /F "UsebackQ Delims=" %%G in ("%~f0:Stream")Do if %%G EQU 0 (
   <nul Set /P "=%\E%[?25h%\E%8%\E[K%"                  %= restore cursor    =%
   %restore.CP% > nul                                   %= restore codepage  =%
   <nul Set /P "=%\E%[7;32m!Params! Complete.%\E%[0m%\E%[1E%\E%[M%\E%[K" %= notify completion; Emit newline; Delete last line of animation =%
   (TITLE )
   Exit                                                 %= exit thread       =%
  ))2> nul

  %= Calculate time elapsed =%
  for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, tDiff=t2-t1"
  if !tDiff! lss 0 set /a tDiff+=24*60*60*100

  if !tDiff! geq !delay! (
   %= delay has expired ; display frame =%
   Set /A T2[L]+=1                %= Increment index point of spinner string =%
   %= Output Spinner frame. Overwites previous output using saved cursor position =%
   For /f "Delims=" %%v in ("!T2[L]!")Do <nul Set /p "=%\E%8%\E%[38;2;20;20;20;7m%\E%[48;2;150;;150m╔═╗╔═╗╔═╗%\E%[0;38;2;150;;150m%\E%[K%\E%[E║%\E%[38;2;20;20;20;7m%\E%[48;2;255;;m!T2[chars]:~%%v,1!%\E%[0m%\E%[38;2;20;20;20;7m%\E%[48;2;150;;150m║║%\E%[38;2;20;20;20;7m%\E%[48;2;;255;m!T2[chars]:~%%v,1!%\E%[0m%\E%[38;2;20;20;20;7m%\E%[48;2;150;;150m║║%\E%[38;2;20;20;20;7m%\E%[48;2;;100;255m!T2[chars]:~%%v,1!%\E%[0m%\E%[38;2;20;20;20;7m%\E%[48;2;150;;150m║%\E%[0m%\E%[K%\E%[E%\E%[38;2;20;20;20;7m%\E%[48;2;150;;150m╚═╝╚═╝╚═╝%\E%[0m%\E%[K%\E%[1G%\E%[2A%\E%7"
   If !T2[L]! EQU 4 Set "T2[L]=0" %= Reset index point of spinner string =%
   set /a t1=t2
  )
 )
Last edited by T3RRY on 05 Jun 2021 07:08, edited 5 times in total.

AR Coding
Posts: 17
Joined: 02 May 2021 21:16

Re: progress bar while doing command

#9 Post by AR Coding » 02 Jun 2021 13:05

Thank you so much, T3RRY! :) You really know your stuff! ;)

Post Reply