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.
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.
#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?
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.
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:
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% overall) then you can use the following each time and simply update the description:
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. 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. Please see the original post for more customisation options.
My internet is not always working properly and I'd like to check the quality based on the cmd windows tool. I believe it's a task simple enough for it to handle.
I've begun by making a shortcut so I can have easy access to the command:
C:\Windows\System32\PING.EXE 8.8.8.8 -t
Now I was trying to transform the cmd ping command into a visually responsive one based on the output. I'd like to make the color change according to the time response.
After looking and not finding anything related, I believe it's either impossible or no one has ever tried.
Thank you very much :)
PD: (In case there was anything unclear just ask and I'll gladly answer)
Based on Magoo's post, I wrote this little batch program.
It asks for the target, the number of requests to make, the max time allowed and the time between requests and then prints in red if the request is over the time max, otherwise it sums the number of requests. It includes timestamp to be more accurate.
Copy and paste in a text file and name it with extension ".bat" (But don't name it "ping.bat" otherwise the program will enter in an infinite loop).
REM CMD PING TOOL
REM By Daweb
REM https://stackoverflow.com/users/3779294/daweb
#ECHO OFF
REM Needed for Line colored
SETLOCAL EnableDelayedExpansion
FOR /F "tokens=1,2 delims=#" %%a IN ('"PROMPT #$H#$E# & echo on & for %%b in (1) do rem"') do (
SET "DEL=%%a"
)
for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
ECHO *****************
ECHO * CMD PING TOOL *
ECHO *****************
REM Start
:start
ECHO.
ECHO Set yours values
REM SET Target
SET /p hostInput=" - Target (ip or hostname): "
If "%hostInput%"=="" ECHO.&GOTO start
REM SET loops
SET /p loopsInput=" - Requests number: "
SET /a loops=loopsInput
REM SET time limit
SET /p maxmsInput=" - Maximum Time Limit (ms): "
SET /a maxms=maxmsInput
REM Value used for sleep between loops
SET /p sleepInput=" - Delay between requests (s): "
SET /a sleepDelay=sleepInput+1
REM Variables
SET displayText=""
SET /a countRequestsOk=0
SET /a countRequestsKo=0
SET /a totalRequests=0
SET /a maxTime=0
ECHO.
ECHO START at %TIME% [target: %hostInput%, requests: %loops%, time limit: %maxms% ms, delay: %sleepInput% s]
ECHO.
REM Loop
:loop
REM Set time
FOR /f "tokens=1-3 delims=/:" %%a IN ("%TIME%") DO (SET mytime=%%ah%%bm%%cs)
REM Get ping value
FOR /f "tokens=3delims==" %%a IN ('PING -n 1 %hostInput%') DO FOR /f "delims=m" %%b IN ("%%a") DO (
SET /a timems=%%b
SET /a totalRequests+=1
REM Check result
IF !timems! GTR %maxms% ( GOTO failed ) ELSE ( GOTO success )
)
REM Request success
:success
SET /a countRequestsOk+=1
IF !timems! GTR !maxTime! ( SET /a maxTime=timems )
<nul set /P "=!countRequestsOk! requests [Max !maxTime! ms]!CR!"
GOTO next
REM Request failed
:failed
IF !countRequestsOk! GTR 0 ECHO.
SET /a countRequestsOk=0
SET /a countRequestsKo+=1
SET displayText=" %mytime% - !timems!ms"
CALL :ColorText 0c !displayText!
GOTO next
REM Next loop
:next
REM Sleep a little bit
IF %sleepDelay% GTR 1 ( ping -n %sleepDelay% localhost > nul )
REM Check continue
SET /a loops-=1
IF %loops% gtr 0 GOTO loop
REM Display result
IF !countRequestsOk! GTR 0 ECHO.
ECHO.
ECHO STOP at %TIME%
ECHO.
if !countRequestsKo! GTR 0 (
SET displayText="FAILED - !countRequestsKo! requests over %maxms% ms on !totalRequests! requests in total"
CALL :ColorText 0c !displayText!
) ELSE (
SET displayText="SUCCESS - No request over %maxms% ms on !totalRequests! requests in total"
CALL :ColorText 02 !displayText!
)
REM Ask if restart
ECHO.&ECHO *********************
SET /p restartInput="Do it again ? (Y/N): "
If "%restartInput%"=="" ECHO *********************&GOTO start
If /I "%restartInput%"=="y" ECHO *********************&GOTO start
If /I "%restartInput%"=="n" ECHO *********************&GOTO end
REM End
:end
PAUSE
GOTO :EOF
REM Line color
:ColorText
ECHO off
ECHO %DEL% > "%~2"
FINDSTR /v /a:%1 /R "^$" "%~2" NUL
DEL "%~2" > NUL 2>&1
#ECHO OFF
SETLOCAL
SET loops=10
:loop
FOR /f "tokens=3delims==" %%a IN ('PING 8.8.8.8 -n 1') DO FOR /f "delims=m" %%b IN ("%%a") DO ECHO %%b&COLOR %%b&GOTO cchgd
:cchgd
PAUSE
SET /a loops-=1
IF %loops% gtr 0 GOTO loop
COLOR
GOTO :EOF
A simple demonstration - repeats the ping 10 times, changing colours depending on the response. Manipulate to do as you wish...
I am not sure that I know what the desired output should be, but this will output GREEN text for response times 0-39 ms, YELLOW for 40-79 ms, and RED for 80+ ms.
Run this from a cmd.exe prompt using the following command or put it into a .bat file script. Change the directory to the location where the Get-PingColor.ps1 file is landed.
powershell -NoLogo -NoProfile -File "%USERPROFILE%\bin\Get-PingColor.ps1"
=== Get-PingColor.ps1
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string[]]$ComputerNames
,[Parameter(Mandatory=$false)]
[int]$Count = 4
,[Parameter(Mandatory=$false)]
[int]$SpeedMinimumSlow = 80
,[Parameter(Mandatory=$false)]
[int]$SpeedMinimumMedium = 40
)
foreach ($ComputerName in $ComputerNames) {
$Pings = Test-Connection -ComputerName $ComputerName -Count $Count
$Average = ($Pings | Measure-Object -Property responsetime -Average).Average
$ForegroundColor = 'Green'
if ($Average -ge $SpeedMinimumSlow) { $ForegroundColor = 'Red'}
else { if ($Average -ge $SpeedMinimumMedium) { $ForegroundColor = 'Yellow' }}
Write-Host -ForegroundColor $ForegroundColor -BackgroundColor 'Black' "$ComputerName $Average ms"
}
=== Execution examples
I am loathe to put images into a post, but I do not see a way to produce color on SO.
I cannot find my bug, after set /p sum=give nr %amount%: it closes.
Does anybody have an Idea why ?
thanks anyway;-)
::Made By QluPreX 29/01/2015
#echo off
cls
color a
:SET_NUM
set /p tot=how many numbers:
cls
set amount=1
set sum_tot=0
echo %tot%?
set /p y_or_n=is that correct (y/n) ? :
if %y_or_n%==y (
cls
goto:GIVE_NUM
) ELSE (
cls
goto:SET_NUM
)
:GIVE_NUM
set /p sum=give nr %amount%:
set /a sum_tot=%sum_tot%+%sum%
set /a amount=%amount%+1
if /I %amount%==%tot%(
goto:DISPLAY
)ELSE(
goto:GIVE_NUM
)
:DISPLAY
echo total is %sum_tot%
pause
No idea what you mean by set /p sum=give nr %amount%:
but
)ELSE(
Must be
) ELSE (
(spaces required)
equally,
if /I %amount%==%tot%(
must be
if /I %amount%==%tot% (
I made a batch file game, and it works, but it is choppy and ugly. I already know about threading, but I don't want to implement that in my first version. I am hoping to have the optimization down before I start doing more advanced things with this game. my question is this: What optimizations can I make to this game, so that it will 1. not be choppy and 2. not be quite so annoying in the display. any ideas or comments about how to make it faster clearer or take less memory are welcome, however, please do not post answers like: "don't use batch" "rewrite it in (insert language here)" "do this part with vb-script" etc... as they are not helpful, nor do they answer the question. any and all non batch hating criticism is welcomed.
here is the code:
#setlocal enableextensions enabledelayedexpansion
#echo off
color 0a
mode con lines=35 cols=50
cls
set instructions=use a and d to move left and right, w to fire. use q to quit and p to pause.
set height=30
set length=
set screen=50
set swidth=20
set amo=8
set lives=3
set 1=0
set 2=1
set 3=2
set 4=3
set 5=4
set 6=0
set 7=1
set 8=2
set 9=3
set 10=4
echo. What quality would you like?
echo. 1. fast, but the graphics suck!
echo. 2. medium both ways.
echo. 3. slow, but the graphics are better!
choice /n /c:123
set firequal=%errorlevel%00
cls
echo %instructions%
echo.
pause
cls
::main
:controls
cls
if %height% EQU 2 goto gameover
if %lives% LSS 1 goto gameover
cls
set /a shouldbomb+=1
set /a whenbomb=shouldbomb%%15
if %whenbomb% == 9 call :bomb
if '%ret%'=='1' exit /b
set ret=
cls
set alive=
for /l %%i in (1,1,10) do if defined %%i set alive=true
if not defined alive goto win
cls
for /l %%i in (1,1,5) do (
if defined %%i (
set /p a=[_] <nul
) else (
set /p a=... <nul
)
)
echo.
for /l %%i in (6,1,10) do (
if defined %%i (
set /p a=[_] <nul
) else (
set /p a=... <nul
)
)
for /l %%a in (1,1,%height%) do echo.
echo %length%[]
echo.
for /l %%i in (1,1,%amo%) do set /p a=^|<nul
echo.
choice /c adwqp0 /n /t 1 /d 0
if %errorlevel% equ 1 goto :left
if %errorlevel% equ 2 goto :right
if %errorlevel% equ 3 goto :fire
if %errorlevel% equ 4 (cls&exit /b)
if %errorlevel% equ 5 pause&goto controls
if %errorlevel% equ 6 goto :inactive
goto controls
::move player left
:left
if '!length!' NEQ '' set length=!length:~0,-1!
goto controls
::move player right
:right
call :strlen shiplen length
if %shiplen% GTR %swidth% goto controls
set length=%length%
goto controls
::fire a shot upwards
:fire
if '!amo!' LSS '1' goto controls
cls
set /a amo-=1
for /l %%i in (%height%,-1,2) do (
cls
for /l %%i in (1,1,5) do (
if defined %%i (
set /p a=[_] <nul
) else (
set /p a=... <nul
)
)
echo.
for /l %%i in (6,1,10) do (
if defined %%i (
set /p a=[_] <nul
) else (
set /p a=... <nul
)
)
for /l %%j in (1,1,%%i) do echo.
echo %length% ^
set /a ship=height-%%i-1
for /l %%b in (1,1,!ship!) do echo.
echo %length%[]
echo.
for /l %%i in (1,1,%amo%) do set /p a=^|<nul
echo.
for /l %%a in (1,1,%firequal%) do call >nul 2>&1
)
call :checkshot
set /a shouldbomb+=1
set /a whenbomb=shouldbomb%%2
if %whenbomb% == 0 call :bomb
goto controls
:inactive
if %amo% LSS 10 set /a amo+=1
if !height! NEQ 2 set /a height-=1
call :bomb
goto controls
:bomb
:btop
set bombx=
for /l %%a in (1,1,10) do (
if defined %%a (
set /a randomnum=%random%%%5
if '!%%a!'=='%randomnum%' (
set /a "bombx=5*(!%%a!)"
)
)
)
)
if not defined bombx goto btop
cls
set bomb=
for /l %%b in (1,1,!bombx!) do (
set bomb=!bomb!
)
set /a bombh=height-1
for /l %%c in (1,1,!bombh!) do (
cls
for /l %%i in (1,1,5) do (
if defined %%i (
set /p a=[_] <nul
) else (
set /p a=... <nul
)
)
echo.
for /l %%i in (6,1,10) do (
if defined %%i (
set /p a=[_] <nul
) else (
set /p a=... <nul
)
)
for /l %%b in (1,1,%%c) do echo.
echo !bomb!x
set /a ship=height-%%c-1
for /l %%b in (1,1,!ship!) do echo.
echo %length%[]
echo.
for /l %%i in (1,1,%amo%) do set /p a=^|<nul
echo.
for /l %%a in (1,1,%firequal%) do call >nul 2>&1
)
if "%bomb%" == "%length%" call :looselife
if "%bomb% " == "%length%" call :looselife
if "%bomb%" == "%length% " call :looselife
if "%bomb% " == "%length%" call :looselife
if "%bomb%" == "%length% " call :looselife
exit /b
:strlen <resultVar> <stringVar>
(
setlocal EnableDelayedExpansion
set "s=!%~2!#"
set "len=0"
for %%P in (1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
)
(
endlocal
set "%~1=%len%"
exit /b
)
:checkshot
call :strlen slen length
for /l %%i in (0,5,20) do (
if '!slen!' == '%%i' (
set /a hit=%%i
set /a hit=hit/5+1
set /a hit2=hit+5
if not defined !hit2! set !hit!=
if defined !hit2! set !hit2!=
)
)
exit /b
:looselife
set /a lives-=1
set length=
set 1=0
set 2=1
set 3=2
set 4=3
set 5=4
if %lives% GTR 1 timeout /nobreak 1 >nul 2>&1
exit /b
:win
cls
echo YOU WIN^!^!^!^!
echo.
echo GOOD JOB^!^!^!
echo.
pause
cls
exit /b
:gameover
cls
echo YOU LOOSE.
echo.
echo PLEASE TRY AGAIN.
echo.
pause
cls
set ret=1
thank you in advance for any help.
P.S. I am writing this game to convince a friend to learn something besides html, and while batch isn't the best, he uses windows, and he will only do something simple for now. He is twelve, so I think batch is best option.
You can definitely improve things considerably. I know, because I have already produced a very smooth and playable version of SNAKE using pure Windows batch! Give it a try - I think you will be surprised and impressed with what musty old batch can do :-)
Of course the link has the code, but it also has pointers on some of the techniques I used to make the came perform so well. Read the entire first post carefully, and read the remainder of the thread for some additional important developments.
Optimization is a large topic. Rather than repeat all the information here, I will simply summarize. Follow the link for more details.
1) Minimize GOTO and CALL statements.
For major speed improvements over traditional batch function calls, we developed batch macros with arguments at DosTips. That first macro link develops a number of important concepts. However, the macro form I actually used in the game uses a more elegant solution with arguments appended.
A GOTO loop can be replaced by an infinite FOR loop that runs in a new process. You break out of the loop by EXITing the child process.
2) Greatly improve key press detection in a non-blocking way.
A major limitation of batch is the inability to easily detect a keypress without blocking progress of the game. The problem can be solved by using two processes, both running in the same console window. The controller process reads keypresses and sends them to the main game process via a text file. The controller has multiple modes of operation. The game process sends commands to the controller via another text file. This technique requires careful coordination of input and output redirection.
The CHOICE command is not available on XP. Some folks at DosTips discovered how to use XCOPY to simulate most of the features of CHOICE, and it works on all versions of Windows. Very cool!
3) Screen painting
Building the screen character by character is extremely slow. It is much faster to build the initial screen once, using an "array" of strings with fixed length. Each character within a string represents one "pixel". The position within a string represents the X coordinate, and the string row number represents the Y coordinate. Generally, only a few pixels change for any given screen refresh. Pixels can be "plotted" by using SET with simple substring operations. The entire screen can then be quickly refreshed using CLS followed by ECHO of each line in the screen array.
4) Smooth animation
The amount of work required to perform game logic and screen plotting can vary significantly depending on the current game context. But you want the animation to be smooth. Rather than have a fixed delay between each round of movement, you can instead measure the time since the screen was last updated. Only continue when a pre-determined amount of time has elapsed. As long as all game logic and plotting can occur within the delay time period, then the animation will always be smooth.
Here is pseudo code that describes the timing logic:
initialize delayTime
initialize previousTime
loop (
get currentTime
set diffTime = currentTime - previousTime
if diffTime >= delayTime (
set previousTime = currentTime
perform user input, game logic, and screen refresh
)
)
And here is actual code that computes the elapsed time since last movement. The currentTime (t2) is measured as centiseconds (1/100 second) since midnight. It is parsed and computed using FOR /F and basic math. The diffTime (tDiff) will be negative if the previousTime (t1) is before midnight and the currentTime (t2) is after midnight. If negative, then 1 day is added to diffTime to get the correct time interval.
%=== compute time since last move ===%
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
There is so much more that can be discussed. Try the SNAKE.BAT game, study the post and the code, and see where your imagination can take you.
Some optimizations
1) It's better to use good variable names.
Names like 1, 2 ... 10 are really bad, nobody knows what they are good for, even you self will not remember in a month.
And then it's also a bad idea as it can have many side effects to use variables begining with digits, in batch there are many where these will simply fail.
2) You should combine your output to complete lines before outputting it.
Then you don't need set/p only echo and it's faster.
3) calls to functions like :strlen should be avoided, calls at all are expensive and in your case it should be possible to solve the same without strlen at all.
4) The function :checkshot don't need a for loop.
I don't understand what you try to do there, but you test slen if it is a muliple of 5.
This could be solved with
set /a remainder=slen %% 5
if !remainder! EQU 0 (
...
5) Follow the tips of dbenham :-)
So I think I have this correct but for some reason it's not reading from the output file "ram.dat". Can anyone find the error in this?
#echo off
set percent=90
:ramcalc
cls
if %percent% GTR 90 Echo Needs To Be Less Than 90
if %percent% LSS 1 Echo Needs To Be Greater Than 1
echo Type Percent Of Ram To Calculate
set /p percent=1-90:
if %percent% GTR 90 goto ramcalc
if %percent% LSS 1 goto ramcalc
cls Calculating...
setlocal ENABLEDELAYEDEXPANSION
set vidx=0
for /F "tokens=*" %%A in (ram.dat) do (
SET /A vidx=!vidx! + 1
set var!vidx!=%%A
echo %%A
)
set var > test.txt
calc %var2%+%var3%+%var4%+%var5% >tmp
set /p add= < tmp
del tmp
calc %add%/1000000 >tmp
set /p divide= < tmp
del tmp
calc %divide%*0.%percent% >tmp
set /p ram= < tmp
del tmp
set /a round=%ram%+0
set ram=%round%
calc %ram%/1024 >tmp
set /p gb= < tmp
del tmp
set /a ramb=%gb%+0
cls
echo %percent% Rounded Is %ram%MB Approxamatly %ramb%GB
pause
goto ramcalc
I'm going to be using this in a dynamic memory modification and it is just a modified sample of my code.
I was typing the answer to your other question when it suddenly vanished. In that question you were dealing with three complexities. 1) Math operations in DOS are limited to 32-bit numbers. 2) WMIC outputs Unicode, so it throws off the for /F command. 3) endlocal discards the ram variable. Here's what I came up to solve all three problems:
#echo off
wmic memorychip get capacity>ram.dat
type ram.dat>ram.txt
setlocal ENABLEDELAYEDEXPANSION
set /p percent=Enter percentage (1-100):
set vidx=0
set var1=0
set var2=0
set var3=0
for /F "skip=1 delims=" %%i in (ram.txt) do (
if "!tmp!" NEQ "" (
SET /A vidx=!vidx! + 1
set var!vidx!=%%i
)
)
set /a var1/=1048576
set /a var2/=1048576
set /a var3/=1048576
set /a total=!var1!+!var2!+!var3!
set ram=!total!MB
del ram.dat
del ram.txt
endlocal &set /a ram=%total% * %percent% / 100
set ram=%ram%MB
set ram
This will calculate the ram for 3 memory card slots, leaving the ram environment variable set at the end of running the batch file. Your new code in your current question looks like you want to calculate a percentage of the available ram. I don't think you can do decimal math in DOS, so you're going to have to use another formula.
Edit 1
I updated the example to include the percentage you included in your second question. You still need to add the bounds checking.