I'm playing around with the new (limited) support for VT-100 escape sequences within the Windows 10 console. The supported sequences are documented at https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx.
In particular, the following sequence that reports the current cursor position interests me.
ESC[6n - responds with ESC[<n>;<m>R,
where <n> is the row number, and <m> the column number
The response is passed off as keyboard input, and appears on the screen, but I have no idea how to programmatically make use of the information. Ideally I would like to get the <n> and <m> values into environment variables from within a batch file.
But if anyone can demonstrate how to capture the variables using any language, then I may be able to use that knowledge to develop an effective batch file strategy.
I can get close with the following simple script called ANSI.BAT
#echo off
setlocal enableDelayedExpansion
for /f "delims=" %%C in (
'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x1B"'
) do set "esc=%%C"
set "csi=%esc%["
echo(Inquiry:%csi%6n
set /p "pos="
echo response=!pos:%esc%=ESC!
--OUTPUT--
C:\test>ansi
Inquiry:
^[[3;9R
response=ESC[3;9R
C:\test>
I can easily parse out the values using FOR /F, once I have the response in a variable. The problem I am having is I must manually press the <Enter> key after the response appears on the screen in order to terminate the input for my SET /P statement. I am stumped on where to go from here...
EDIT - One last requirement: I don't want the inquiry response to appear on the screen, as that disrupts the screen, and changes the cursor position. I suspect this may be the toughest nut to crack, perhaps impossible with pure batch.
Major change after three years
It works with reading the response by using XCOPY or REPLACE.
I'm using replace here, to avoid language dependent problems.
#echo off
for /F "delims=#" %%a in ('"prompt #$E# & for %%a in (1) do rem"') do set "ESC=%%a"
call :get_cursor_pos
exit /b
:get_cursor_pos
set "response="
set pos=2
:_get_loop
REM *** Request Cursor position
<nul set /p "=%ESC%[6n"
FOR /L %%# in (1 1 %pos%) DO pause < CON > NUL
for /F "tokens=1 skip=1 eol=" %%C in ('"REPLACE /W ? . < con"') DO (
set "char=%%C"
)
set "response=%response%%char%"
set /a pos+=1
if "%char%" NEQ "R" goto :_get_loop
set response
exit /b
The main problem is, XCOPY or REPLACE allows me to read one character from the input stream, but then clears the remaining buffer.
Conversely, PAUSE reads one character, preserving the remaining buffer, but does not reveal what character was read.
To solve this, I issue the query multiple times, reading a different character of the response each time. For each iteration I use a combination of 2 or more PAUSE statements followed by REPLACE to read a specific character of the response. Each iteration uses one more PAUSE than the prior iteration, until I am able to read the terminating R.
I developed this technique and initially posted it at DosTips - Query States using Console Virtual Terminal Sequences.
I have NOT Windows 10, so I can't complete any test. However, if the response of the Ansi ESC[6n sequence is fill the keyboard input buffer with ESC[<n>;<m>R characters, then it is just necessary to add an Enter key to such input in order to read it via SET /P command, and this can be done via SendKeys JScript method.
I also used a simpler method to get an ESC character in a variable.
EDIT: I modified the code accordingly to comments...
#if (#CodeSegment == #Batch) #then
#echo off
title Ansi Test
setlocal EnableDelayedExpansion
for /F %%a in ('echo prompt $E ^| cmd') do set "esc=%%a"
set "csi=%esc%["
echo Inquiry:%csi%6n
cscript //nologo //E:JScript "%~F0"
set /p "pos=" > NUL
echo response=!pos:%esc%=ESC!
#end
var sh = WScript.CreateObject("WScript.Shell");
sh.AppActivate("Ansi Test");
sh.SendKeys("{ENTER}");
Please, post the result...
Related
This question already has answers here:
Is there anyway to have preset data for user input in a batch file?
(6 answers)
Closed 4 years ago.
My trouble is to read a string from test.txt and type it in as a console command.
Example:
user is asked to provide a path to their sandbox folder and at the same time in a console it is already offered (from a saved test.txt), only waiting for the user to hit ENTER
Path to your sandboxes folder: C:\Whatever\Path\Sandboxes
Where Path to your sandboxes folder: is part of a set /p command in a script waiting for an input; and C:\Whatever\Path\Sandboxes has been typed-in by the script as a pre-offered path. From here the user can either hit ENTER, if satisfied with offered path or edit it: C:\Whatever\OtherPath\Sandcastles
I assume, the first step would be to read from test.txt into a variable, but how do I proceed from there? How do i type the characters of this string variable into a console?
By combining it with cscript.
#if (#CodeSection == #Batch) #then
#echo off
for /f "tokens=* delims=" %%i in (test.txt) do set "output=%%I"
CScript //nologo //E:JScript "%~F0" "%output%"
set /P "var=Path to your sandboxes folder: "
echo selected path = %var%
goto :EOF
#end
WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0));
not possible with pure batch, but you can use a default value (because set /p doesn't touch the variable, when you just press ENTER):
for /f "tokens=1,* delims=:" %%a in (test.txt) do (
set "folder=%%b"
set /p "folder=%%a (ENTER for default [%%b]) : "
)
echo "%folder%"
Note: there is a space at the start of the %folder%. Easy to avoid, when you remove the space from test.txt:
Path to your sandboxes folder:C:\Whatever\Path\Sandboxes
If in said test.txt the first line only contains the default path, you could use this:
SET /P _path=<test.txt
SET /P _path=%_path%
This is the fastest way to achieve this, but it only works with the 1st line (read more).
If it is e.g. in the 3rd line use this:
FOR /F "skip=2 delims=" %%G IN ("C:\adjust\path\test.txt") DO (SET "_path=%%G" & GOTO break)
:break
SET /P _path=%_path%
For the 5th line change skip=2 to skip=4, for the 17th line to skip=16; basically if the path is in line n you want to skip n-1 lines.
You could also use FINDSTR, but this is unecessary as long as the location of the path in test.txt is known.
I have to run an executable (written in C#) 42 times separately for 42 US states on Windows command line. I wrote a batch file to automate the process. The 1st user input to the executable is 1, and the 2nd one is the state abbreviation (AL, AZ, CT etc.). I have written the following script to do it:
#echo off
for /f "tokens=1 delims=" %%x in (CropHailStates.txt) do (
(echo 1 & echo %%x)|Z:\Models\LossCalc.exe
)
Each row in CropHailStates.txt file contains the state abbreviation as follows:
AL
AZ
CT
Now in manual mode, when 1 is entered at the 1st prompt and AL is entered at the 2nd, the C# program reads a file named "AL.Even.CropLoss.csv". But when I run the batch script to do it automatically, I get the error message saying that the file "AL .Even.CropLoss.csv" is not found. The problem is related to the extra whitespace after AL. It’s somehow adding the whitespace after inserting the state abbreviation. It’s like pressing the spacebar after writing the state abbreviation, but before pressing enter.
How can I get rid of that extra whitespace in the file name?
The problem is an artifact of the pipe parser when dealing with a parenthesized block of code.
The source of the problem is described by jeb at Why does delayed expansion fail when inside a piped block of code?.
Each side of the pipe is executed in a new CMD /C process.
When a multi-line parenthesized block gets piped, the parser must repackage the entire block into a single line so that it can be executed via CMD /C
(
echo line 1
echo line 2
) | findstr "^"
The left side of the pipe is executed as:
C:\WINDOWS\system32\cmd.exe /S /D /c" ( echo line 1 & echo line 2 )"
You can see the extra spaces that are introduced.
Even though your code is already on a single line, it still goes through the same parser that introduces those pesky spaces.
I know of three relatively simple solutions that eliminate the unwanted spaces without the need for a temporary file.
1) Add an extra CMD /C where you explicitly get the exact behavior you are looking for
#echo off
for /f "tokens=1 delims=" %%x in (CropHailStates.txt) do (
cmd /c "echo 1&echo %%x"|Z:\Models\LossCalc.exe
)
2) Store part of the command in a variable and delay expansion until execution of CMD /C
#echo off
setlocal
for /f "tokens=1 delims=" %%x in (CropHailStates.txt) do (
set "cmd=&echo %%x"
(echo 1%%cmd%%)|Z:\Models\LossCalc.exe
)
3) Introduce delayed expansion of a linefeed variable - a mind blowing technique developed by jeb that he describes in that same SO link that I provided
#echo off
setlocal
set ^"LF=^
%= This creates a linefeed character =%
"
for /f "tokens=1 delims=" %%x in (CropHailStates.txt) do (
(echo 1%%LF%%echo %%x%%LF%%)|Z:\Models\LossCalc.exe
)
(echo 1& echo %%x)>tempfile.txt
Z:\Models\LossCalc.exe <tempfile.txt
del tempfile.txt
should provide the data without the trailing spaces
To get rid of the last character (the whitespace) you can do:
#echo off
setlocal EnableDelayedExpansion
for /f "tokens=1 delims=" %%x in (CropHailStates.txt) do (
set "result=%%x"
(echo 1 & echo !result:~0,-1!)|Z:\Models\LossCalc.exe
)
Hope it helps.
#echo off
:prep
cls
for /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
:for /l %A in (1,1,100) do copy "C:\some folder\file.ext" "C:\some folder\file-%%A.ext"
set choice=
:: test to see if directory exists
if EXIST "../delivery_%mydate%.txt" (
goto overwrite
) else (
goto start
)
:overwrite
echo.
echo delivery note already exists - continue?
set /p choice='y / n ?'
if '%choice%'=='' ECHO "%choice%" is not valid please try again
if '%choice%'=='y' goto start
if '%choice%'=='n' goto end
echo.
:start
echo.
for /l %A in (1,1,100) do copy "C:\some folder\delivery_%mydate%.ext" "C:\some folder\delivery_%mydate%.ext"
echo Choose the following:
echo 1. Directories
echo 2. Files
echo 3. quit
echo.
set /p choice=
if '%choice%'=='1' goto directory
if '%choice%'=='2' goto file
if '%choice%'=='3' goto end
cls
ECHO "%choice%" is not valid please try again
goto start
:directory
dir /ad /on /b > ../delivery_%mydate%.txt
echo.
goto checksuccess
:file
dir /a-d /on /b > ../delivery_%mydate%.txt
echo.
goto checksuccess
:checksuccess
I need to add a line of code to this batch file I have created above. I need this code to save an existing file to a higher version without deleting the previous one. This will also need to be embedded into the code I created. For example it will start saving them like: filev001, filev002, etc.
1. Some general advice for writing batch files
A list of commands is output on executing in a command prompt window help. It is advisable to use in batch files for environment variables and labels not a string which is also a command. It is possible, but not advisable.
start is a command to start an application in a separate process. So it is better to use for example Begin instead of start as label.
choice is a command for a choice which is better for single character choices than using set /P. So it is better to use for example UserChoice instead of just choice as environment variable name.
It is better to use echo/ instead echo. to output an empty line. The reason is explained by DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/.
Environment variable names and labels are easier to read on using CamelCase and can be more easily searched case-sensitive and if necessary replaced in a batch file than a name/label which can exist as word also in comments and in strings output with echo.
The answer on question Why is no string output with 'echo %var%' after using 'set var = text' on command line? explains in detail why the usage of the syntax set "Variable=string value" is recommended in batch files on assigning a string to an environment variable.
The directory separator on Windows is the backslash character \. The slash character / is the directory separator on Unix/Linux/Mac. On Windows / is used for options/parameters. The Windows kernel functions support also directory and file paths with / as directory separator by automatically correcting them to \ internally in path. But it is nevertheless recommended to use in a batch file \ in paths.
rem is the command for a comment in a batch file. :: is an invalid label and not really a comment. Lines with a label at begin are ignored for command execution. But a label cannot be used in a command block. For that reason it is recommended to use command rem because :: in a command block results often in unexpected behavior on execution of the batch file.
2. Get current date in a specific format
Let us look on the command line:
for /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c-%%a-%%b)
date /t is a command which for executes in a background command process with the command line cmd.exe /C date /t for capturing the output of this command process written to standard output handle STDOUT and process the captured output line by line.
Can this be optimized?
Yes, because on running in a command prompt window set /? and reading the output help from first to last page it can be read that there is the environment variable DATE which expands to current date. So there is no need to run the command date to get current date as string.
The command date with option /t outputs the current date in the format defined for the used user account in Windows Region and Language settings. In your case it looks like the region dependent date format is MM/dd/yyyy with the weekday abbreviation at beginning (with no comma) before the date. The date format on my computer is just dd.MM.yyyy without weekday. The environment variable DATE is in same region dependent format as output of command date /t.
So the region dependent date in format ddd, MM/dd/yyyy could be also modified to yyyy-MM-dd using the command line:
for /F "tokens=2-4 delims=/, " %%a in ("%DATE%") do set "MyDate=%%c-%%a-%%b"
It is also possible to use string substitution:
set "MyDate=%DATE:~-4%-%DATE:~-10,2%-%DATE:~-7,2%"
String substitution is also explained by help output on running set /? and read the answer on
What does %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% mean?
But if yyyy-MM-dd is the wanted date format for current date independent on region settings of the used user account is advisable to use the command lines
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "MyDate=%%I"
set "MyDate=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%"
This region independent solution is really much slower than the above command lines. It is explained in detail by the answer on Why does %date% produce a different result in batch file executed as scheduled task? But it has the big advantage of being region independent.
3. Prompting user for a single character choice
The usage of set /P variable=prompt is not recommended for a single character choice because
the user can just hit RETURN or ENTER without entering anything at all resulting in variable keeping its current value or still not being defined if not defined before set /P command line;
the user can make a typing mistake and presses for example Shift+2 instead of just 2 resulting (on German keyboard) to enter " as string which most batch files using set /P breaks because of a syntax error on next command line evaluating the user input;
the user can enter anything instead of one of the characters asked for including strings which on next command line results in deletion of files and folders.
The solution is using the command choice if that is possible (depends on Windows version). choice waits for the key press of a character specified in the command options and immediately continues after one of these keys is pressed. And choice exits with the index of the pressed character in list as specified in batch file. This exit code is assigned to ERRORLEVEL which can be evaluated next also within a command block without using delayed expansion or used directly in a single goto instruction.
4. Rewritten batch file
Here is the rewritten batch file:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem set "Folder=C:\some folder"
set "Folder=F:\Temp\Test"
:Prepare
cls
rem Get current date region independent in format yyyy-MM-dd.
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "MyDate=%%I"
set "MyDate=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%"
set "FileNumber=0"
for %%I in ("%Folder%\file-*.ext") do call :GetFileNumber "%%~nI"
goto IncrementNumber
rem Subroutine to find out highest file number without using delayed
rem environment variable expansion for number range 0 to 2147483647.
rem Numbers starting with 0 are interpreted as octal number in number
rem comparison which makes it necessary to remove leading 0 from the
rem number string get from file name starting with 5 characters.
:GetFileNumber
set "Number=%~1"
set "Number=%Number:~5%
:RemoveLeadingZero
if "%Number%" == "" goto :EOF
if "%Number:~0,1%" == "0" set "Number=%Number:~1%" & goto RemoveLeadingZero
if %Number% GTR %FileNumber% set "FileNumber=%Number%"
goto :EOF
rem Make sure the file number has at least 3 digits.
:IncrementNumber
set /A FileNumber+=1
if %FileNumber% GEQ 100 goto ExistDelivery
set "FileNumber=00%FileNumber%"
set "FileNumber=%FileNumber:~-3%"
rem Test to see if file exists already.
:ExistDelivery
if not exist "..\delivery_%MyDate%.txt" goto Begin
echo/
%SystemRoot%\System32\choice.exe /C YN /N /M "Delivery note already exists, continue (Y/N)? "
if errorlevel 2 goto :EOF
:Begin
set "FileName=file-%FileNumber%.ext"
copy "%Folder%\file.ext" "%Folder%\%FileName%" >nul
echo/
echo Choose the following:
echo/
echo 1. Directories
echo 2. Files
echo 3. Quit
echo/
%SystemRoot%\System32\choice.exe /C 123 /N /M "Your choice? "
if errorlevel 3 goto :EOF
if errorlevel 2 goto GetFileList
dir * /AD /ON /B >"..\delivery_%MyDate%.txt"
echo/
goto CheckSuccess
:GetFileList
dir * /A-D /ON /B >"..\delivery_%MyDate%.txt"
echo/
:CheckSuccess
rem More commands.
endlocal
It was not really clear for me what the entire batch code is for at all.
It would have been also easier to write the determination of highest number in a file name on knowing the possible number range like 001 to 100. So I wrote a general solution for 001, 002, ..., 099, 100, 101, ..., 1000, ..., 2147483647.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
cls /?
copy /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
wmic /?
wmic os /?
wmic os get /?
wmic os get localdatetime /?
See also answer on Single line with multiple commands using Windows batch file for an explanation of & operator and read the Microsoft article about Using command redirection operators.
So, I've been trying to create a simple spinning line thing that goes on for a set number of loops. I've encountered a problem: I can't find a way to add to a variable, or have a loop counter. This is my code so far (Other general criticisms are accepted too: I'm new to this and it all helps.)
#echo off
:1
echo
echo
echo
echo -
echo
cls
echo
echo
echo /
echo
cls
echo
echo
echo I
echo
cls
echo
echo
echo \
echo
cls
echo
echo
echo -
echo
IF %timer%
goto 1
pause
Really sorry if it's already been asked; I just can't seem to find what I'm looking for. Also, it's very possible this could just be a simple command, in which case i apologise again.
There's a couple of errors with your code as it stands.
The major one is
IF %timer%
goto 1
Batch is a ver old-fashioned language and is very particular about syntax. You can get a syntax description by typing
if /? |more
at the prompt. (replace if with the keyword you desire)
if requires
if string1==string2 thingtodoiftrue
Over the years, the syntax has been expanded, still maintaining the old version for compatibility so that the general form is now
if string1==string2 (thingtodoiftrue) else (thingtodoiffalse)
where == may now be a number of operators (equ, neq, ...); you can add a /i switch to make the strings case-insensitive, or a not keyword to reverse the sense. The parentheses are optional if the thingtodo is a single statement.
There are some quirky syntax requirements however. Either thingtodoiftrue or ( must be on the same physical line as the if keyword. The sequence ) else ( must all be on one physical line (if it's used)
As for performing some variety of count using your original structure, there are many ways. Here's one:
#echo off
set count=15
:1
....
set /a count=count-1
IF %count% neq 0 goto 1
pause
This may be what you are looking for. This runs the code 10000 times and it could be modified according to your need.
#echo off
for /l %%i in (1,1,10000) do (
echo -
cls
echo /
cls
echo I
cls
echo \
cls
)
Cheers, G
#echo off
setlocal enableextensions disabledelayedexpansion
rem Get a 0x13 character (carriage return) char inside a variable
for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
rem Spin the line
setlocal enabledelayedexpansion
for /l %%a in (1 1 5000) do for %%b in (- \ ^| /) do (
set /a "pct=%%a / 50"
<nul set /p ".=%%b !pct!%% !cr!"
)
endlocal
The basic idea is to output the spinning element, followed by the percentage. To keep all the output in the same line
<nul set /p "var=outputtext"
is used. This echoes the indicated text to console, waits for input, that is readed from nul, ending the prompt wait and continues without moving the cursor to the next line. There is no line feed
Now, it is necessary overwrite this line with the new information each time. To do it, it is necessary to get a carriage return character into a variable. For it, the for /f is used, retrieving the needed carriage return character from the output of the copy command.
note: the disabledelayedexpansion is necessary in this step to avoid problems if the full path/filename of the batch file (%~f0) contains any exclamation character.
The remaining code just iterates painting the corresponding character in the list, calculating the percentage to output and printing all to the console, without the line feed (<nul set /p ...) but with an aditional carriage return that moves the cursor to the start of the line. So, the next output will overwrite the previous one
note: in this case, enabledelayedexpansion is needed to get access to the content of the changed percentage variable and to output the carriage return. Without delayed expansion active, the parser removes the carriage return from the output.
I have made a batch game where users can log in / register. But there is no point in having passwords if a person standing nearby can peep at the password. Normal password fields mask the characters with asterisks (*).
How can mask characters on a batch file?
I've seen this done on cmd before but I have no clue how.
You can use XCOPY for a hidden input, it can handle nearly all characters and you can also implement a backspace logic.
#echo off
setlocal EnableDelayedExpansion
call :input
echo(
echo '!input!'
if "!input!"=="password" echo OK
exit /b
:input
for /F "tokens=1 delims=# " %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do (
set "\b=%%a"
)
set "input="
:keyLoop
call :GetKey
if not defined key exit /b
if "!key!"=="!\b!" (
if defined input (
set "input=!input:~0,-1!"
<nul set /p ".=!\b! !\b!"
)
) ELSE (
<nul set /p ".=*"
set "input=!input!!key!"
)
goto :keyLoop
:GetKey
setlocal DisableDelayedExpansion
set "key="
for /F "usebackq delims=" %%L in (`xcopy /L /w "%~f0" "%~f0" 2^>NUL`) do (
if not defined key set "key=%%L"
)
(
endlocal
set "key=^%key:~-1%" !
exit /b
)
This code should be able to handle all characters, like ^!&%<>.
It's also possible to use backspace to delete the last entered character.
The line set "key=^%key:~-1%" ! seems odd, but it's used to escape the ! character with set "key=^!" ! in the delayed expansion context.
And to avoid problems for all other characters the last ! removes the caret, like in set "key=^A" ! will be evaluated to ``set "key=A"`
Ok, this is a bit different to what you may have had in mind, but that's you're fault for choosing batch for game dev.
The way I see it is you have 3 options:
Use an external program you self made in C#, C++, Python, [etc.]
Howver this requires an application to already do this for you (Which there probably is) or for you to have a knowledge in one of these languages
Use the choice command, to continuously take one key input and wait for the user to hit space to signify the end of the password
However this limits the password characters choice, and makes the program look ugly
Use 2 Batch threads, one that masks and tallies input while the other stores it to a variable.
This may be a bit dodgey at times, at would be a bit complicated but may be the only choice you have.
Now, as I was typing this an idea stuck my head on how to achieve this. Since it might take some time to test I thought I'd post the idea (as it seems to be a soloution to this problem, which has been around for a while).
Logic
One Batch Thread will simply use set /p to store all the input into a variable and upon completion will communicate to the other batch thread through the use of waitfor or a simple directory file.
Another Batch Thread would loop the pause >nul statement and would tally the number of times the pause statement is looped, printing out the appropriate amount of *'s. The other important job of this thread is to sense when the user has finished typing the password, upon which it exits.
Im starting to make this batch program now, but for now I'll just keep you informed of my idea so far.
Code
Login.bat
#echo off
Title Password Please:
:: This is the main code
REM This code relies on Masker.bat
REM SET password to be first and thrid letter,
REM of the day of the week.
set pass=%Date:~0,1%%Date:~2,1%
REM START Masker in the same window using /b tag and create hold.pass:
Echo 0 >%temp%\hold.pass
start /b Masker.bat "%pass%" *
REM Simply take input an leave the rest to Masker.bat
set /p pass_input=:
Echo 1 >>%temp%\hold.pass
cls
if /i "%pass%" NEQ "%pass_input%" (
Title Worng Password
Echo Wrong Password... Sorry.
Sleep 5
Exit
)
Pause > nul
REM Rest of Main game code is below or simply
:: START Main.bat & Exit
Masker.bat
#echo off
Title Password Please:
setlocal enabledelayedexpansion
:: This is not the main code
REM This code is called upon by Login.bat (or the Main.bat game code)
REM CREATE the variables "passlen" and "mask":
set password=%~1
set passlen=0
:miniloop
set /a passlen+=1
if "!password:~%passlen%,1!" NEQ "" goto :miniloop
set password=
set mask=%~2
if "%mask%" EQU "" set mask=*
REM MAIN loop
:loop
cls
for /l %%a in (1,1,%passlen%) do (<nul set /p=%mask%)
sleep -m 150
for /f "usebackq" %%a in ("%temp%\hold.pass") do (if "%%~a" EQU "1" Del %temp%\hold.pass & Exit)
goto :loop
It still needs some more improvements, but I've spent aroung 30 min on it with little success to make it dynamically tell you how many characters you have typed in.
Anyone cane take this up, be my guest. Everything else works fine
Mona
This works without pressing enter after input of the password.
If you enter the correct password, ok.
if you enter a wrong password, it will stop when you enter the 9th character (can be adapted).
It does not care about capitalization.
Problem: the password is stored as pure text in the code
#echo off
setlocal enabledelayedexpansion
set "s= abcdefghijklmnopqrstuvwxyz"
set p=
:loop
choice /C %s% /N >nul
set p=%p%!s:~%errorlevel%,1!&set /p =*<nul
if /i "%p%"=="secured" goto :right
if not "%p:~8,1%"=="" goto :wrong
goto :loop
goto :wrong
:right
echo you entered correct password: %p%
goto :eof
:wrong
echo you entered wrong password: %p%
goto :eof
You may use ReadFormattedLine subroutine for all kind of formatted input. For example, the command below read a password of 8 characters, display asterisks in the screen, and continue automatically with no need to press Enter:
call :ReadFormattedLine password="********" /M "Enter password (8 chars): "
This subroutine is written in pure Batch so it does not require any additional program, and it allows several formatted input operations, like read just numbers, convert letters to uppercase, etc. You may download ReadFormattedLine subroutine from Read a line with specific format.