How can I get my status (String) to blink in my batch file? - batch-file

I'd like my string to blink in my batch file. The below works well for me. My job's computer logs me out soon after the 11th hour so I like a visual fair warning for that so my batch file does that. Below is my code so far but my string status doesn't blink.
#Echo off
mode 22,15
Color B
cls
set /a Minutes=0
set /a Time=0
Set /a Hours=0
Set /a Reset=11
set Str=Good
For /F "Tokens=*" %%I in ('Time /T') Do Set mytime=%%I
:hi
cls
Echo.
Echo Started %mytime%
Echo Status: %Str%
Echo.
Echo Time so far:
Echo.
Echo %Hours% Hours
Echo.
Echo %Minutes% Minutes
Echo.
Echo %Time% Seconds
Echo.
Echo %Reset% Hours to Reset
ping localhost -n 2 >nul
set /a time=%time%+1
if %time%==60 (
goto min
)else goto :hi
:min
set /a Time=0
set /a Minutes=%Minutes%+1
if %Minutes%==60 (
goto hours
)else goto :hi
goto hi
:hours
set /a Minutes=0
Set /a Reset=%Reset%-1
set /a Hours=%Hours%+1
if %Hours%==11 (
color 47
set Str=ResetEmement
) else goto :hi
goto hi

Related

Issues with rpg stat system

Im making an rpg game in batch, and here is the code for the stat system so far
:SPSPEND
CLS
Echo You have %SP% stat points to spend, every stat point used increases that skill by 5.
Echo 1. Strength=%Strength%
Echo 2. Agility=%Agility%
Echo 3. Magic=%Magic%
Echo 4. Vitality=%MaxHP%
Echo 5. Defence=%Defence%
Echo 6. Archery=%Archery%
set /p choice=Choose what to put points into:
if %choice%=="1" Set /a Strength==%strength%+5
if %choice%=="2"
if %choice%=="3"
if %choice%=="4"
if %choice%=="5"
if %choice%=="6"
cls
set /a SP==%SP%-1
goto :rest
Not sure how to format soz. i need help with two things : how can i make it so that it doesnt close out and actually works, and how can i make a failsafe incase a person enters something other than what i already have set up.
Thanks in advance
I believe this is what you want.
I have tested it and am fairly certain it will work
:SPSPEND
CLS
if %SP% leq 0 goto end
Echo You have %SP% stat points to spend, every stat point used increases that skill by 5.
Echo 1. Strength=%Strength%
Echo 2. Agility=%Agility%
Echo 3. Magic=%Magic%
Echo 4. Vitality=%MaxHP%
Echo 5. Defence=%Defence%
Echo 6. Archery=%Archery%
set /p choice=Choose what to put points into:
if "%choice%"=="1" Set /a Strength=%Strength%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="2" Set /a Agility=%Agility%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="3" Set /a Magic=%Magic%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="4" Set /a MaxHP=%MaxHP%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="5" Set /a Defence=%Defence%+5& set /a SP=%SP%-1& goto SPSPEND
if "%choice%"=="6" Set /a Archery=%Archery%+5& set /a SP=%SP%-1& goto SPSPEND
echo invalid choice
pause
goto SPSPEND
cls
:end
pause
goto :rest

Batch file to Schedule and Reschedule Future Shutdowns

Edit 27-05-2918 (related question): I am wondering why a scheduled shutdown this way is not shown in the "Task Scheduler" (Windows 10)?
I have a .BAT with some code, I want to add the following to it.:
Tell user is there is currently a shutdown activated (If the BAT is
ran more than once before shutdown) and when that shutdown is scheduled for.
Currently when trying to reschedule the shutdown, the BAT displays errorlevel 1990, I need a way for it not to show that message.
And I would also like to try the following (I am not too sure how to do it.)
if X=List, shows multiple future shutdowns scheduled (date and times), at particular dates, and also shows re-occurring scheduled shutdowns.
Be able to add or remove individual future shutdowns, or edit them, etc.
The code below works pretty well, but without achieving points .1 .2 and .3
Edit:
Updated code, I have managed to solve point .2: using 2>NUL
#echo off
setlocal enabledelayedexpansion
goto :MAIN
:INVALID
Echo X = "%input01%" is invalid.
timeout 5
goto :MAIN
:NOW
C:\Windows\System32\shutdown /s
Echo Shutting down now.
pause
goto :MAIN
:STOP
Echo Attempting to stop any Scheduled Shutdowns.
Echo/
C:\Windows\System32\shutdown /a 2>NUL
if NOT ERRORLEVEL 1116 (Echo Scheduled shutdown stopped.) ELSE (
Echo Unable to abort the system because no shutdown was in progress (1116^)
)
Timeout 10
goto :MAIN
:MAIN
cls
set "input01="
set "ExVal01="
Echo JimmyWilliams - 20180523
Echo/
Echo This will cause the computer to automatically shutdown in X minutes,
Echo and will override any existing scheduled shutdown.
Echo/
Echo Enter "X = Stop", cancel any currently active future shutdown.
Echo Enter "X = Quit", to close this program.
Echo/
Set /p "input01=1. Enter a whole positive number: X = "
if "%input01%"=="" goto :INVALID
Set /a ExVal01="%input01%"*60
if /I "%input01%"=="Quit" goto :Quit
if /I "%input01%"=="Stop" goto :STOP
if %input01%==0 goto :NOW
if %ExVal01%==0 goto :INVALID
if %input01% LSS 0 goto :INVALID
C:\Windows\System32\shutdown /s /t %ExVal01% 2>NUL
if ERRORLEVEL 1190 (echo Rescheduled to shutdown in %input01% mins.
C:\Windows\System32\shutdown /a
C:\Windows\System32\shutdown /s /t %ExVal01%
) ELSE (echo Shutting down in %input01% mins.
)
Timeout 10
goto :MAIN
:QUIT
Echo Quiting the Program.
pause
:EOF:
This is my working code.
I would greatly appreciate it if anyone knows of any tricks to remove redundancies or speed the code up, or make it cleaner, that would be awesome! I'm a newb, so feel free to give suggestions and comments.
Thanks!
James
::20180618
::JamesShaw
::Description: This program allows users to schedule a future shutdown, and cancel them.
::
::Bug:
:: If shutdown is scheduled far into the future, and then computer is shutdown before this scheduled shutdown
:: Program will continue to say the future date even though it is no longer scheduled.
:: Remove by typing "Stop" or entering new shutdown.
::Warning: Does not show the timer when shutdown will occur.
#echo off
setlocal enabledelayedexpansion
::Checks to make sure that WMIC.EXE exists, to get date and time (independent of how the computer's time is displayed/region settings).
cls
WMIC.EXE Alias /? >NUL 2>&1 || GOTO Exe_DNE_Error
goto :CURRENT
:Exe_DNE_Error
Echo WMIC.EXE is not installed; this program cannot obtain dates and times to show when a shutdown is scheduled until this EXE is available.
pause
goto :QUIT
:INVALID
Echo X = "%input01%" is invalid.
timeout 5
goto :CURRENT
:NOW
C:\Windows\System32\shutdown /s
Echo Shutting down now.
Echo You have a few seconds to type "Stop", if you wish.
timeout 5
goto :CURRENT
:STOP
Echo Attempting to stop any Scheduled Shutdowns.
Echo/
C:\Windows\System32\shutdown /a 2>NUL
if NOT ERRORLEVEL 1116 (Echo Scheduled shutdown stopped.) ELSE (
Echo Unable to abort the system because no shutdown was in progress (1116^)
)
If EXIST "%~dp0Schdule Scheduler(TEMP).txt" del "%~dp0Schdule Scheduler(TEMP).txt"
timeout 5
goto :RESETSCHEDULE
:TOOLARGE
Echo X = "%input01%" is invalid.
Echo X must be less than 5256000 (10 years).
timeout 5
goto :CURRENT
:CURRENT
:: Use WMIC to retrieve current date and time.
:: Compares current time and date to the Scheduled shutdown within "Schdule Scheduler(TEMP).txt"
FOR /F "skip=1 tokens=1-6" %%G IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO (
IF "%%~L"=="" goto s_done
Set _yyyy=%%L
Set _mm=00%%J
Set _dd=00%%G
Set _hr=00%%H
Set _mi=00%%I
)
:s_done
:: Pad digits with leading zeros
Set _mm=%_mm:~-2%
Set _dd=%_dd:~-2%
Set _hr=%_hr:~-2%
Set _mi=%_mi:~-2%
:: Display the date/time in ISO 8601 format:
Set _isodate=%_yyyy%-%_mm%-%_dd% %_hr%:%_mi%
If EXIST "%~dp0Schdule Scheduler(TEMP).txt" goto :SCHEDULECHECKER
goto :RESETSCHEDULE
:SCHEDULECHECKER
set /p PulledDate=<"%~dp0Schdule Scheduler(TEMP).txt"
Set _ySch=%PulledDate:~0,4%
Set _mthS=%PulledDate:~5,2%
Set _dSch=%PulledDate:~8,2%
Set _hSch=%PulledDate:~11,2%
Set _mSch=%PulledDate:~14,2%
Set _dateSch=%_ySch%-%_mthS%-%_dSch% %_hSch%:%_mSch%
If /I %_ySch% LSS %_yyyy% goto :RESETSCHEDULE
If /I %_ySch% EQU %_yyyy% If /I %_mthS% LSS %_mm% goto :RESETSCHEDULE
If /I %_ySch% EQU %_yyyy% If /I %_mthS% EQU %_mm% If /I %_dSch% LSS %_dd% goto :RESETSCHEDULE
If /I %_ySch% EQU %_yyyy% If /I %_mthS% EQU %_mm% If /I %_dSch% EQU %_dd% If /I %_hSch% LSS %_hr% goto :RESETSCHEDULE
If /I %_ySch% EQU %_yyyy% If /I %_mthS% EQU %_mm% If /I %_dSch% EQU %_dd% If /I %_hSch% EQU %_hr% If /I %_mSch% LSS %_mi% goto :RESETSCHEDULE
goto :MAIN
:RESETSCHEDULE
If EXIST "%~dp0Schdule Scheduler(TEMP).txt" del "%~dp0Schdule Scheduler(TEMP).txt"
Set "_ySch="
Set "_mthS="
Set "_dSch="
Set "_hSch="
Set "_mSch="
Set "_dateSch="
goto :MAIN
:MAIN
cls
if "%_dateSch%"=="" (set _dateSch1=No Scheduled Shutdown.) ELSE (
Set _dateSch1=%_dateSch%
)
set "input01="
set "ExVal01="
Echo JamesShaw - 20180618
Echo/
Echo This will cause the computer to automatically shutdown in X minutes,
Echo and will override any existing scheduled shutdown.
Echo/
Echo Current clock time is: %_isodate%
Echo Shutdown scheduled at: %_dateSch1%
Echo/
Echo Enter "X = Stop", cancel any currently active future shutdown.
Echo Enter "X = Quit", to close this program.
Echo/
Set /p "input01=1. Enter a whole positive number: X = "
if "%input01%"=="" goto :INVALID
Set /a ExVal01="%input01%"*60
if /I "%input01%"=="Quit" goto :QUIT
if /I "%input01%"=="Stop" goto :STOP
if /I %input01% GEQ 5256000 GOTO :TOOLARGE
if %input01%==0 goto :NOW
if %ExVal01%==0 goto :INVALID
if %input01% LSS 0 goto :INVALID
C:\Windows\System32\shutdown /s /t %ExVal01% 2>NUL
if ERRORLEVEL 1190 (echo Rescheduled to shutdown to %input01% mins from now.
C:\Windows\System32\shutdown /a
C:\Windows\System32\shutdown /s /t %ExVal01%
) ELSE (echo Shutdown to %input01% mins from now.
)
Set /a _mSch=input01+_mi
Set /a _hSch=_mSch/60
Set /a _mSch=_mSch%%60
Set /a _hSch=_hSch+_hr
Set /a _dSch=_hSch/24
Set /a _hSch=_hSch%%24
Set /a _dSch=_dSch+_dd
pause
goto :FEB
:FEB
::Tests to see if the month of Feburary is a leap year for that year or not.
Set /a test1=_yyyy%%4
Set /a test2=_yyyy%%100
Set /a test3=_yyyy%%400
Set /a test4="" 2>NUL
if /I %_mm% EQU 2 (
if /I %test1% EQU 0 (
if /I %test2% EQU 0 (
if /I %test3% EQU 0 (Set /a test4=29) ELSE (Set /a test4=28)
) ELSE (Set /a test4=29)
) ELSE (Set /a test4=28)
GOTO :MYBREAK
)
GOTO :MONTH31
:MONTH31
FOR %%G IN (1 3 5 7 8 10 12) DO (
if /I %_mm% EQU %%G (Set /a test4=31
GOTO :MYBREAK)
)
Set /a test4=30
GOTO :MYBREAK
:MYBREAK
if /I %_dSch% GTR %test4% (
Set /a _dSch=_dSch-test4
if /I %_mm% EQU 12 (
Set /a _yyyy=_yyyy+1
Set /a _mm=1
) ELSE (Set /a _mm=_mm+1)
GOTO :FEB
)
Set "_mSch=00%_mSch%
Set _mSch=%_mSch:~-2%
Set "_hSch=00%_hSch%
Set _hSch=%_hSch:~-2%
Set "_dSch=00%_dSch%
Set _dSch=%_dSch:~-2%
Set "_mm=00%_mm%"
Set _mm=%_mm:~-2%
:: Display the date/time in ISO 8601 format:
Set _isodate=%_yyyy%-%_mm%-%_dSch% %_hSch%:%_mSch%
> "%~dp0Schdule Scheduler(TEMP).txt" Echo %_yyyy%-%_mm%-%_dSch% %_hSch%:%_mSch%
Goto :CURRENT
:QUIT
Echo Quiting the Program.
pause
:EOF:
Here is another simpler version without the calendar and timer of the scheduled shutdown
(works without the EXE).
::20180527
::JamesShaw
::Description: This program allows users to schedule a future shutdown, and cancel them.
::
::Warning: Does not show the timer when shutdown will occur
#echo off
setlocal enabledelayedexpansion
goto :MAIN
:INVALID
Echo X = "%input01%" is invalid.
timeout 5
goto :MAIN
:NOW
C:\Windows\System32\shutdown /s
Echo Shutting down now.
pause
goto :MAIN
:STOP
Echo Attempting to stop any Scheduled Shutdowns.
Echo/
C:\Windows\System32\shutdown /a 2>NUL
if NOT ERRORLEVEL 1116 (Echo Scheduled shutdown stopped.) ELSE (
Echo Unable to abort the system because no shutdown was in progress (1116^)
)
Timeout 10
goto :MAIN
:MAIN
cls
set "input01="
set "ExVal01="
Echo JamesShaw - 20180523
Echo/
Echo This will cause the computer to automatically shutdown in X minutes,
Echo and will override any existing scheduled shutdown.
Echo/
Echo Enter "X = Stop", cancel any currently active future shutdown.
Echo Enter "X = Quit", to close this program.
Echo/
Set /p "input01=1. Enter a whole positive number: X = "
if "%input01%"=="" goto :INVALID
Set /a ExVal01="%input01%"*60
if /I "%input01%"=="Quit" goto :Quit
if /I "%input01%"=="Stop" goto :STOP
if %input01%==0 goto :NOW
if %ExVal01%==0 goto :INVALID
if %input01% LSS 0 goto :INVALID
C:\Windows\System32\shutdown /s /t %ExVal01% 2>NUL
if ERRORLEVEL 1190 (echo Rescheduled to shutdown in %input01% mins.
C:\Windows\System32\shutdown /a
C:\Windows\System32\shutdown /s /t %ExVal01%
) ELSE (echo Shutting down in %input01% mins.
)
Timeout 10
goto :MAIN
:QUIT
Echo Quiting the Program.
pause
:EOF:

how to change the text assigned to a variable in batch

So I am having a problem with changing a text assinged using the set /a
here is my script
:wep
cls
if %gold% lss 50 (
echo not enough gold
pause >nul
goto shop
)
if %weap%==Stick (
echo too low on level
pause >nul
goto shop
)
if %wepugrd% lss 1 (
echo You don't have any upgrades
pause
goto shop
)
cls
echo Your Weapon is Being Upgraded
echo.
echo WAIT A FEW SECONDS
ping localhost -n 3 >nul
set /a weapdmg=%weapdmg% + 5
set /a weap=Stick
set /a wepugrd=%wepugrd% - 1
set /a gold=%gold% - 50
echo weapon upgraded
pause
goto shop
the last part is set /a weap=Stick
it was earlier fist
but instead it just changes fist to 0 instead of changing it to stick
can I get some help with that
thanx
Use this code:
:wep
cls
if %gold% lss 50 (
echo not enough gold
pause >nul
goto shop
)
if "%weap%"=="Stick" (
echo too low on level
pause >nul
goto shop
)
if %wepugrd% lss 1 (
echo You don't have any upgrades
pause
goto shop
)
cls
echo Your Weapon is Being Upgraded
echo.
echo WAIT A FEW SECONDS
%SystemRoot%\System32\ping.exe localhost -n 3 >nul
set /a weapdmg+=5
set "weap=Stick"
set /a wepugrd-=1
set /a gold-=50
echo weapon upgraded
pause
goto shop
As npocmaka wrote, switch /A is only for arithmetic operations and can't be used if just a string should be assigned to a variable.
Adding or subtracting an integer to an existing value can be also done using the short form as demonstrated above.
And read this answer for reason enclosing weap=Stick in double quotes.

How to generate a random number between 1 and 100 using batch

%random% seems to go in order.
#ECHO OFF
SET /A RAND=%RANDOM% %%100
ECHO %RAND%
ECHO.
If you keep running this it increments until it reaches 100 and then the number start over. If it were random it would jump around.
#ECHO OFF
SET /A RAND=%RANDOM%
ECHO %RAND%
ECHO.
SET /A RAND=%RANDOM%%%100+1
this may work.
If I understoof the question right, here's what you're looking for.
echo off
title Number from 1 to 100.
color 0a
cls
:loop
cls
set /a rand=%random% %%101
echo %rand%
pause >nul
goto loop
hey if the problem still persists
use this code
this generates a number between a and b
tweak it to your needs
#echo off
color 02
echo enter value of A
set /p a=
echo.
echo enter value of B
set /p b=
:main
set no=%random%
if %no% GEQ %a% goto sub
if not %no% GEQ %a% goto main
:sub
if %no% LEQ %b% goto end
if not %no% LEQ %b% goto main
:end
echo %no%
goto main

How to code a spinner for waiting processes in a Batch file?

I would like to show the user with a spinner, that something is done in background but do not know how this works in a batchfile.
Does anyone have a clue?
This can actually be done quite easily with pure native commands, you just have to know how to use the more tricky of them. No use of external tools like VBScript or nasty side effects like clearing the screen are necessary.
What you're looking for is the equivalent of the bash "echo -n" command which outputs a line without the newline. In XP batch, this is achieved by using "set /p" (ask user for response with a prompt) with empty input as follows:
<nul (set /p junk=Hello)
echo. again.
will output the string "Hello again." with no intervening newline.
That trick (and the use of CTRL-H, the backspace character can be seen in the following test script which starts (one after the other) a 10-second sub-task with a 20-second timeout and a 15-second sub-task with a 10-second timeout.
The payload script is created by the actual running script and its only requirement is that it do the work it has to do then delete a flag file when finished, so that the monitor function will be able to detect it.
Keep in mind that the ^H strings in this script are actually CTRL-H characters, the ^| is two separate characters used to escape the pipe symbol.
#echo off
:: Localise environment.
setlocal enableextensions enabledelayedexpansion
:: Specify directories. Your current working directory is used
:: to create temporary files tmp_*.*
set wkdir=%~dp0%
set wkdir=%wkdir:~0,-1%
:: First pass, 10-second task with 20-second timeout.
del "%wkdir%\tmp_*.*" 2>nul
echo >>"%wkdir%\tmp_payload.cmd" ping 127.0.0.1 -n 11 ^>nul
echo >>"%wkdir%\tmp_payload.cmd" del "%wkdir%\tmp_payload.flg"
call :monitor "%wkdir%\tmp_payload.cmd" "%wkdir%\tmp_payload.flg" 20
:: Second pass, 15-second task with 10-second timeout.
del "%wkdir%\tmp_*.*" 2>nul:
echo >>"%wkdir%\tmp_payload.cmd" ping 127.0.0.1 -n 16 ^>nul
echo >>"%wkdir%\tmp_payload.cmd" del "%wkdir%\tmp_payload.flg"
call :monitor "%wkdir%\tmp_payload.cmd" "%wkdir%\tmp_payload.flg" 10
goto :final
:monitor
:: Create flag file and start the payload minimized.
echo >>%2 dummy
start /min cmd.exe /c "%1"
:: Start monitoring.
:: i is the indicator (0=|,1=/,2=-,3=\).
:: m is the number of seconds left before timeout.
set i=0
set m=%3
<nul (set /p z=Waiting for child to finish: ^|)
:: Loop here awaiting completion.
:loop
:: Wait one second.
ping 127.0.0.1 -n 2 >nul
:: Update counters and output progress indicator.
set /a "i = i + 1"
set /a "m = m - 1"
if %i% equ 4 set i=0
if %i% equ 0 <nul (set /p z=^H^|)
if %i% equ 1 <nul (set /p z=^H/)
if %i% equ 2 <nul (set /p z=^H-)
if %i% equ 3 <nul (set /p z=^H\)
:: End conditions, complete or timeout.
if not exist %2 (
echo.
echo. Complete.
goto :final
)
if %m% leq 0 (
echo.
echo. *** ERROR: Timed-out waiting for child.
goto :final
)
goto :loop
:final
endlocal
If you don't mind the screen clearing...try this:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET COUNT=1
START CALC
:BEGIN
CLS
IF !COUNT! EQU 1 ECHO \
IF !COUNT! EQU 2 ECHO -
IF !COUNT! EQU 3 ECHO /
IF !COUNT! EQU 4 ECHO -
IF !COUNT! EQU 4 (
SET COUNT=1
) ELSE (
SET /A COUNT+=1
)
PSLIST CALC >nul 2>&1
IF %ERRORLEVEL% EQU 1 GOTO END
GOTO BEGIN
:END
EDIT: This sample will start Calculator and then display a "spinner" until you close Calculator. I use pslist to check for the existence of CALC.EXE. The >nul 2>&1 redirects STDOUT and STDERR to nul so nothing from PSLIST will be displayed.
Try this:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
CALL :BACKSPACE $BS
SET /A FULL_COUNT=60
SET /A MAX_COUNT=160
SET /A Spin_Delay=50
SET "_MSG=Process running..."
SET /A CTR=0
SET /A TCT=0
IF NOT [%1]==[] SET _MSG=%~1
IF NOT [%2]==[] SET /A FULL_COUNT=%2
IF NOT [%3]==[] SET /A SPIN_DELAY=%3
IF %FULL_COUNT% GTR %MAX_COUNT% SET FULL_COUNT=%MAX_COUNT%
(SET/P=%_MSG%*)<nul
FOR /L %%A IN (1,1,%FULL_COUNT%) DO (
CALL :DELAY %SPIN_DELAY%
IF !CTR! EQU 0 (set/p=%$BS%³)<nul
IF !CTR! EQU 1 (set/p=%$BS%/)<nul
IF !CTR! EQU 2 (set/p=%$BS%Ä)<nul
IF !CTR! EQU 3 (set/p=%$BS%\)<nul
SET /A CTR=%%A %% 4
)
(SET/P=%$BS%*)<nul
ENDLOCAL & EXIT /B %CTR%
:BackSpace
setlocal
for /f %%a in ('"prompt $H$S &echo on &for %%b in (1) do rem"') do set "Bs=%%a"
endlocal&call set %~1=%BS%&exit /b 0
:Delay msec
setlocal enableextensions
set/a correct=0
set/a msecs=%1+5
if /i %msecs% leq 20 set /a correct-=2
set time1=%time: =%
set/a tsecs=%1/1000 2>nul
set/a msecs=(%msecs% %% 1000)/10
for /f "tokens=1-4 delims=:." %%a in ("%time1%") do (
set hour1=%%a&set min1=%%b&set sec1=%%c&set "mil1=%%d"
)
if /i %hour1:~0,1% equ 0 if /i "%hour1:~1%" neq "" set hour1=%hour1:~1%
if /i %min1:~0,1% equ 0 set min1=%min1:~1%
if /i %sec1:~0,1% equ 0 set sec1=%sec1:~1%
if /i %mil1:~0,1% equ 0 set mil1=%mil1:~1%
set/a sec1+=(%hour1%*3600)+(%min1%*60)
set/a msecs+=%mil1%
set/a tsecs+=(%sec1%+%msecs%/100)
set/a msecs=%msecs% %% 100
:: check for midnight crossing
if /i %tsecs% geq 86400 set /a tsecs-=86400
set/a hour2=%tsecs% / 3600
set/a min2=(%tsecs%-(%hour2%*3600)) / 60
set/a sec2=(%tsecs%-(%hour2%*3600)) %% 60
set/a err=%msecs%
if /i %msecs% neq 0 set /a msecs+=%correct%
if /i 1%msecs% lss 20 set msecs=0%msecs%
if /i 1%min2% lss 20 set min2=0%min2%
if /i 1%sec2% lss 20 set sec2=0%sec2%
set time2=%hour2%:%min2%:%sec2%.%msecs%
:wait
set timen=%time: =%
if /i %timen% geq %time2% goto :end
goto :wait
:end
for /f "tokens=2 delims=." %%a in ("%timen%") do set num=%%a
if /i %num:~0,1% equ 0 set num=%num:~1%
set/a err=(%num%-%err%)*10
endlocal&exit /b %err%
If I understand your question you want a spinner because some operation you are performing is taking time and you want to show to the user that something is happening, right?
In that case, as far as I know, its not possible with the native commands. (it could be possible if you had a program that showed a spinner while executing the operation that take long time)
And it looks like the echo don't support ansi escape sequences (in the old days you had to have ansi.sys loaded, don't know if that still exists) so you can't use ansi to control the cursor.
The spinner CAN be done in batch script, you just need some variables:
#echo off
:spinner
set mSpinner=%mSpinner%.
if %mSpinner%'==..............................' set mSpinner=.
cls
echo %mSpinner%
rem Check if the process has finished via WMIC and/or tasklist.
goto spinner
:exit
For the BAT itself to detect a process running/exits. You can do that via the WMI command-line interface or the tasklist command of which I have limited knowledge.
If it were back in the DOS days you could even does that without clearing the screen... short of using some combination of escape characters. I don't know if it's still possible on Vista/XP.
If you mean within a Windows batch script, you can't do it natively. The echo statement used to print to the console will always print a newline, and you can't move the cursor.
It's a bit of a hack, but you can do this with a combination of VBScript and batch script.
This VBScript will print a backspace, then it's argument:
WScript.StdOut.Write(chr(8) & WScript.Arguments(0))
Put this in a file, vbsEcho.vbs, then call this script from your batch script. The following batch script will keep displaying the spinner until you press CTRL-C:
#echo off
:LOOP
cscript //nologo vbsEcho.vbs "\"
cscript //nologo vbsEcho.vbs "|"
cscript //nologo vbsEcho.vbs "/"
cscript //nologo vbsEcho.vbs "-"
goto :LOOP
EDIT: Using some of the ideas from aphoria's answer, this script will start the Windows calculator, and display a spinner until the calculator closes:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET COUNT=1
START CALC
cscript //nologo vbsEcho.vbs "Calculating: \"
:LOOP
IF !COUNT! EQU 1 cscript //nologo vbsEcho.vbs "|"
IF !COUNT! EQU 2 cscript //nologo vbsEcho.vbs "/"
IF !COUNT! EQU 3 cscript //nologo vbsEcho.vbs "-"
IF !COUNT! EQU 4 (
cscript //nologo vbsEcho.vbs "\"
set COUNT=1
) else (
set /a COUNT+=1
)
pslist CALC >nul 2>&1
if %ERRORLEVEL% EQU 1 goto :end
goto :LOOP
:END
cscript //nologo vbsEcho.vbs ". Done."
paxdiablos has an amazing answer, but having to echo your commands into a payload file is annoying. It's hard to read and hard to debug. I took his code and modified it a bit for my own use:
#echo off
:: Localise environment.
setlocal enableextensions enabledelayedexpansion
set wkdir=%~dp0%
set wkdir=%wkdir:~0,-1%
set done_flag="%wkdir%\tmp_payload.flg"
set timeout=7
:controller
IF (%1)==() (
call :monitor step1 "Getting stuff from SourceSafe: "
call :monitor step2 "Compiling some PHP stuff: "
call :monitor step3 "Finishing up the rest: "
) ELSE ( goto %1 )
goto final
:step1
::ping for 5 seconds
ping 127.0.0.1 -n 6 >nul
del "%wkdir%\tmp_payload.flg"
goto final
:step2
::ping for 10 seconds
ping 127.0.0.1 -n 11 >nul
del "%wkdir%\tmp_payload.flg"
goto final
:step3
::ping for 5 seconds
ping 127.0.0.1 -n 6 >nul
del "%wkdir%\tmp_payload.flg"
goto final
:monitor
:: Create flag file and start the payload minimized.
:: echo the word "dummy" to the flag file (second parameter)
echo >>%done_flag% dummy
:: start the command defined in the first parameter
start /min cmd.exe /c "test2.bat %1"
:: Start monitoring.
:: i is the indicator (0=|,1=/,2=-,3=\).
:: m is the number of seconds left before timeout.
set i=0
set m=%timeout%
set str=%2
for /f "useback tokens=*" %%a in ('%str%') do set str=%%~a
<nul (set /p z=%str%^|)
:: Loop here awaiting completion.
:loop
:: Wait one second.
ping 127.0.0.1 -n 2 >nul
:: Update counters and output progress indicator.
set /a "i = i + 1"
set /a "m = m - 1"
if %i% equ 4 set i=0
if %i% equ 0 <nul (set /p z=^|)
if %i% equ 1 <nul (set /p z=/)
if %i% equ 2 <nul (set /p z=-)
if %i% equ 3 <nul (set /p z=\)
:: End conditions, complete or timeout.
if not exist %done_flag% (
::echo.
echo Complete
goto :final
)
if %m% leq 0 (
echo.
echo. *** ERROR: Timed-out waiting for child.
goto :final
)
goto :loop
:final
endlocal
You can use a counter that prints a different character from a given set (like "\|/-") and you change the character according to like "counter modulo 4". Anyway, you don't say in which language you're working in so it is a bit difficult to be more precise.
EDIT: now that we know in which environment you're playing in, I'd say that the BAT/CMD language is not really up to the task... I'd recommend any scripting language, Ruby being my favorite.
I find the easiest way is to update the title - that way you don't have to do a CLS all the time.
The reason for the two lines of ping -n, is that it's quicker for ping to do a double ping of a second each, versus a single ping of two seconds.
Also, for those who don't know, a :: is the same as a REM, except that the comments are ignored at the beginning of the parser (I think this is the right word) instead of at the end. Simply put, that line is ignored.
:: begin spin.cmd
#echo off
setlocal
set COUNT=0
set MAXCOUNT=10
set SECONDS=1
:LOOP
title "\"
call :WAIT
title "|"
call :WAIT
title "/"
call :WAIT
title "-"
if /i "%COUNT%" equ "%MAXCOUNT%" goto :EXIT
set /a count+=1
echo %COUNT%
goto :LOOP
:WAIT
ping -n %SECONDS% 127.0.0.1 > nul
ping -n %SECONDS% 127.0.0.1 > nul
goto :EOF
:EXIT
title FIN!
endlocal
:: end spin.cmd
This routine examines the output of tasklist for a process you START from cmd.
Pass it the name of the exe as a parameter e.g.
call :spinner calc.exe
It reports
Elapsed: 001 seconds
and increments seconds until the exe process terminates.
The Elapsed 001 seconds message is overwritten each second by ECHO.exe -n \r
which echos a cr without a line feed.
Echo.exe is available at
http://www.paulsadowski.com/wsh/cmdprogs.htm
#echo off
start calc
call :spinner calc.exe
pause
:spinner
SET COUNT=1
:BEGIN
set "formattedValue=000000%count%"
ECHO.exe -n Elapsed: %formattedValue:~-3% seconds
ECHO.exe -n \r %= -n (suppress crlf) \r output a cr =%
SET /A COUNT+=1
set EXE=%1 %= search output of tasklist for EXE =%
set tl=tasklist /NH /FI "IMAGENAME eq %EXE%"
FOR /F %%x IN ('%tl%') DO IF %%x == %EXE% goto FOUND
set result=0
goto FIN
:FOUND
set result=1
:FIN
IF %result% EQU 0 GOTO END
PING -n 2 127.0.0.1 > nul %= wait for about 1 second =%
GOTO BEGIN
:END
start application, wait for loading
#echo off & setlocal enabledelayedexpansion
start application.exe
:1
for %%a in (^| ^/ ^- ^\ ^| ^/ ^- ^\) do (
for %%b in (^| ^/ ^- ^\ ^| ^/ ^- ^\) do (
for %%c in (^| ^/ ^- ^\ ^| ^/ ^- ^\) do (
cls &echo processing..%%c%%b%%a
sleep -m 20
IF EXIST "result file" (exit)
)))
goto 1
:LOOP
ECHOX -n "~r%Processing..."
IF %CTR% EQU 4 SET /A CTR=0
IF %CTR%==0 (set /p DOT=³)<NUL
IF %CTR%==1 (set /p DOT=/)<NUL
IF %CTR%==2 (set /p DOT=Ä)<NUL
IF %CTR%==3 (set /p DOT=\)<NUL
ECHOX -n "~r"
SET /A CTR+=1
SET /A TCT+=1
IF %TCT% GTR %MAX_COUNT% GOTO :END
GOTO :LOOP

Resources