secure password protected batch - batch-file

I am currently making password protected batch file,
and the problem is when I type #echo on or %#echo on% it shows the password, (one moment, but if you do video you can see it clearly).
When I changed 3rd line to this if "%pwd%"==somepassword, then by typing #echo on again shows the password.
I have some few ideas. For ex. make #echo off unchangeable, or character escaping, but I am not that good at batch scripting so I can't write it by code.
Is there anyone who can help me with this?
#echo off
set /p pwd="Enter password: "
if %pwd%==somepassword (cmd /k) else (exit)

There could be used:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "pwd="
:PwdPrompt
set /P "pwd=Enter password: " || goto PwdPrompt
setlocal EnableDelayedExpansion
if not "!pwd!" == "somepassword" exit /B
endlocal
echo The password is correct!
echo/
pause
endlocal
There is first defined the required execution environment completely with
turning off command echo mode and
enabling command extensions and
disabling delayed variable expansion.
The environment variable pwd is next explicitly undefined. The user must enter a password.
The user is prompted for the password and this is done in a loop as long as the user does not enter a string at all. So no input is not accepted by the batch file.
Then delayed variable expansion is enabled before doing the string comparison with making use of delayed variable expansion to prevent a modification of the batch file code for execution by the string input by the user.
If the two compared strings are not equal, the batch file processing (not necessarily the command process) is exited which results in implicit execution of endlocal twice by cmd.exe for the two setlocal before really exiting the processing of the batch file.
Otherwise on input password string being equal the password string in the batch file the previous local environment with disabled delayed expansion is restored before the batch file processing is continued with the next commands.
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.
echo /?
endlocal /?
goto /?
if /?
pause /?
set /?
setlocal /?
I strongly recommend to read also:
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
It explains in full details why this code is fail-safe and secure.
Single line with multiple commands using Windows batch file
It explains in full details the meaning of the command operator ||.
Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files
It explains in full details how a string comparison is done with command IF.
How to pass environment variables as parameters by reference to another batch file?
It explains in full details the commands SETLOCAL and ENDLOCAL.
DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/

Related

How to save a variable to a batch file?

This is my code:
set /p name=user save name
if %name%==[""]
cd c:\users\student\desktop\login system\usersXD
echo set "name=%name%"> %name%.bat
My code is not working. and i will like to load them up to view
I suggest following code for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
goto PromptName
:ErrorInvalid
echo/
echo Error: The character !InvalidChar! is not allowed in name.
echo/
endlocal
:PromptName
set "Name="
set /P "Name=User save name: "
rem Has the user not input anything?
if not defined Name goto PromptName
rem Remove all double quotes from input string.
set "Name=%Name:"=%"
rem Has the user input just double quotes?
if not defined Name goto PromptName
rem Check if the input string contains any character not allowed in a file name.
setlocal EnableDelayedExpansion
for %%I in ("<" ">" ":" "/" "\" "|") do if not "!Name:%%~I=!" == "!Name!" set "InvalidChar=%%~I" & goto ErrorInvalid
if not "!Name:?=!" == "!Name!" set "InvalidChar=?" & goto ErrorInvalid
if not "!Name:**=!" == "!Name!" set "InvalidChar=*" & goto ErrorInvalid
endlocal
cd /D "%UserProfile%\Desktop\login system\usersXD"
echo set "Name=%Name%">"%Name%.bat"
endlocal
The file name of the batch file to create must be enclosed in double quotes because it could contain a space or one of these characters &()[]{}^=;!'+,`~ which require enclosing the file name in double quotes.
This batch file should not be stored in directory %UserProfile%\Desktop\login system\usersXD on having file extension .bat as it could be overwritten during execution if the user enters a name the name of the batch file. It would be safe to have this batch file in that directory with file extension .cmd.
The batch file is still not 100% fail-safe despite the checks already added, but the user input string itself cannot result anymore in an exit of batch file execution because of a syntax error.
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.
cd /?
echo /?
endlocal /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
See also:
Wikipedia article listing the predefined Windows environment variables like UserProfile
Single line with multiple commands using Windows batch file explaining the operator &
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
Microsoft documentation page Using command redirection operators explaining the redirection operator >
Microsoft documentation page Naming Files, Paths, and Namespaces listing which characters are not allowed in file/folder names
This should work to save a variable in a bat file
If I remember
(
Echo set test=%
Echo set test=%test%
Echo set test=%test%
)>Test.bat

Using CMDER, issue with setting PATH

I'm trying to use CMDER for a development environment that I've setup.
Basically I've created a .bat file that calls:
#ECHO OFF
start Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\Cmder.exe
Then I've placed the file startdev.bat in:
%CMDER_HOME%\config\profile.d
So everything seems to work just fine, but when the startdev.bat finishes, issuing an:
echo %PATH%
returns:
Z:\_DEV\OS_WINDOWS\1_COMPILER\JDK\ORACLE\1.8.0_181\bin;Z:\_DEV\OS_CYGWIN\bin;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CLutils;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\PUTTY;Z:\_DEV\OS_WINDOWS\6_VERSION_CONTROL\PortableGit\bin;C:\WINDOWS;C:\WINDOWS\SysWOW64;C:\WINDOWS\System32
...any idea what's happening?
I would either expect CMDER to override PATH with the value from its own settings, or use my full path, which before the startdev.bat ends shows the value of:
PATH=Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5\ConEmu;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5\ConEmu\Scripts;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\GRADLE\5.4\bin;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\MAVEN\3.5.4\bin;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\ANT\1.10.5\bin;Z:\_DEV\OS_WINDOWS\3_BUILD_TOOLS\NODE\LTS\10.15.3;Z:\_DEV\OS_WINDOWS\3_BUILD_TOOLS\NODE\LTS\10.15.3\node_modules;Z:\_DEV\OS_WINDOWS\1_COMPILER\GO\1.12.4\bin;Z:\_DEV\OS_WINDOWS\1_COMPILER\PYTHON\32bit\2.7.13;Z:\_DEV\OS_WINDOWS\1_COMPILER\PYTHON\32bit\2.7.13\scripts;Z:\_DEV\OS_WINDOWS\1_COMPILER\ANDROID\android-sdk-windows\platform-tools;Z:\_DEV\OS_WINDOWS\1_COMPILER\JDK\ORACLE\1.8.0_181\bin;Z:\_DEV\OS_CYGWIN\bin;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CLutils;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\PUTTY;Z:\_DEV\OS_WINDOWS\6_VERSION_CONTROL\PortableGit\bin;C:\WINDOWS;C:\WINDOWS\SysWOW64;C:\WINDOWS\System32
..but the fact that it only seems to be keeping the value as defined about halfway through the batch job is strange.
Any ideas?
First I recommend opening a command prompt window and run setlocal /? and endlocal /? to get displayed the help/documentation for those two commands. Very important to know is that every setlocal without a corresponding endlocal results in an implicit execution of endlocal by cmd.exe before exiting processing of a batch file or a subroutine called with command CALL.
Next I suggest reading this answer for even more details about the commands SETLOCAL and ENDLOCAL and what happens on using them.
I suggest like michael_heath to change this code block:
setLocal EnableDelayedExpansion
set CLASSPATH=.
for /R %JRE_HOME%\lib %%a in (*.jar) do (
set CLASSPATH=!CLASSPATH!;%%a
)
set CLASSPATH=!CLASSPATH!
Better would be:
setLocal EnableExtensions EnableDelayedExpansion
set CLASSPATH=.
for /R "%JRE_HOME%\lib" %%a in (*.jar) do set "CLASSPATH=!CLASSPATH!;%%a"
endlocal & set "CLASSPATH=%CLASSPATH%"
Now the local environment is ended with passing the environment variable CLASSPATH from local environment, on which it was defined, to the restored previous environment because of cmd.exe expands %CLASSPATH% to current value of the environment variable CLASSPATH in current local environment before executing the command endlocal which restores the previous environment.
Wrong in your batch file is also set WINDIR=%SystemRoot%;%SystemRoot% which should be set "WINDIR=%SystemRoot%".
I recommend further reading Why is no string output with 'echo %var%' after using 'set var = text' on command line? It explains why the syntax set "variable=string value" is recommended nowadays. Many of the environment variable definitions use directly or indirectly %UserProfile% which means depending on whatever the user currently running the batch file has entered as user name on creation of the user account. I have seen users entering their name containing a space and non ASCII characters. And I have seen users creating an account with a user name containing character & like Company GmbH & Co. An ampersand outside a double quoted argument string is interpreted as AND operator and cmd.exe tries to execute after set also the remaining string after & as command line on using something like set USERHOME=%DEVHOME%\%USERNAME% instead of set "USERHOME=%DEVHOME%\%USERNAME%". Well, startdev.bat redefines nearly all predefined Windows Environment Variables including USERNAME and USERPROFILE and so is written safe for most environment variable definitions.
This code block is also not optimal:
FOR /F "usebackq" %%i IN (`hostname`) DO SET HOSTNAME=%%i
echo Running on hostname: %HOSTNAME%
The host name respectively computer name could contain also a space or characters critical for command line or start with a semicolon for some unknown reason. So better would be:
FOR /F delims^=^ eol^= %%i IN ('hostname') DO SET "HOSTNAME=%%i"
setlocal EnableDelayedExpansion & echo Running on host name: !HOSTNAME!& endlocal
Whereby there is the environment variable COMPUTERNAME predefined by Windows making it possible to use just following command line:
setlocal EnableDelayedExpansion & echo Running on host name: !ComputerName!& endlocal
An ECHO command line containing an immediately expanded environment variable reference on which it is unknown if its value contains &|<> is always a problem because of the environment variable reference is expanded before further processing of the command line by cmd.exe as described at How does the Windows Command Interpreter (CMD.EXE) parse scripts?
I suggest also reading DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ and avoid the usage of echo. in the batch file to output an empty line.
"halfway through the batch job" as you have a
setLocal EnableDelayedExpansion which sets any further
changes to the variable PATH or other set variables as local.
The endLocal not specified is implied at the end of the script.
To resolve this, use endLocal and set CLASSPATH=%CLASSPATH%
on the same parsed line to set CLASSPATH as global.
Change this part:
setLocal EnableDelayedExpansion
set CLASSPATH=.
for /R %JRE_HOME%\lib %%a in (*.jar) do (
set CLASSPATH=!CLASSPATH!;%%a
)
set CLASSPATH=!CLASSPATH!
to this:
setLocal EnableDelayedExpansion
set CLASSPATH=.
for /R %JRE_HOME%\lib %%a in (*.jar) do (
set CLASSPATH=!CLASSPATH!;%%a
)
endLocal & set CLASSPATH=%CLASSPATH%
After that changed part, the script will set variables as global again.

Create Batch File

I have this assignment from my teacher in regards to creating a batch file that does something. its pretty huge assignment, but one part i stuck. it asks:
If the value of the userdomain variable is equal to the value of the computername variable then
Store into a file called output.txt the following information:
1. The current username
2. The current computername
So im thinking, my username(domain username) would never be same as a computer name anywhere in the world! lol
So that would NEVER happen! in this case i should do nothing!
So im confused. What am i missing?!
It is possible to give the computer the name of the user account in a domain. That is not forbidden. That your computer has a different name than your user account in domain or locally does not mean it is not possible.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
:RunNameCompare
if /I "%COMPUTERNAME%" == "%USERNAME%" (
setlocal EnableDelayedExpansion
echo User name: !USERNAME!>output.txt
echo Computer name: !COMPUTERNAME!>>output.txt
endlocal
) else (
echo/
echo Computer name and user account name are different.
echo/
%SystemRoot%\System32\choice.exe /N /M "Simulate identical names [Y/N]: "
if not errorlevel 2 set "COMPUTERNAME=%USERNAME%" & goto RunNameCompare
)
endlocal
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.
choice /?
echo /?
endlocal /?
goto /?
if /?
set /?
setlocal /?
See also the following pages and articles:
Wikipedia article about Windows Environment Variables
Microsoft article about Using Command Redirection Operators
Microsoft article about Testing for a Specific Error Level in Batch Files
Single line with multiple commands using Windows batch file
This answer for details about the commands SETLOCAL and ENDLOCAL
DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/
The outer SETLOCAL and ENDLOCAL are used to create a local environment on running this batch file so that even after taking the simulate identical names option, the predefined environment variable COMPUTERNAME has its original value after running the batch file from within a command prompt window as recommended on debugging and verifying a batch file in development.
The inner SETLOCAL and ENDLOCAL are used to be able to output correct into file output.txt even computer and user account names containing command line critical characters like &()[]{}^=;!'+,`~|<> or ending with a space and a number in range 1 to 9 without enclosing both names in double quotes.

How to change a string in a FOR loop by adding the loop number at the end of the string?

I have a problem when using the loop. What I want to do is to change the file name by adding a number "N" at the end of the file name in each iteration, like file1, file2, file3, ... So it should not overwrite the previous file name.
set path=D:\MeasurementData\%~n0%
echo %path%
pause
for /L %%N in (1,1,5) do (
set file="%path%%%N"
echo %file%
pause
start C:\TomoK.exe %file% "D:\MParameter.mff" "D:\MParameter.mcf"
Pause
)
Does anyone know how to solve this?
My first suggestion is never replacing a predefined environment variable like PATH except there is a very good reason to do it. Open a command prompt window and run set to get output all predefined variables with their current values. Or look on Wikipedia article about environment variables the chapter Windows Environment Variables and read answers on What is the reason for '...' is not recognized as an internal or external command, operable program or batch file?
My second suggestion on needing help it is advisable to open a command prompt window and run each command used in batch file with /? as parameter like set /?. Then the help for the command is output on one or more pages which can be studied. How to use delayed expansion and when it must be used is explained by help of command SET on an IF and a FOR example. Other helpful pages on writing batch files are Microsoft's command-line reference and SS64.com - A-Z index of the Windows CMD command line.
My third suggestion is reading answer on How to set environment variables with spaces? and the other Stack Overflow question linked there. And the second half on this answer with details about the commands SETLOCAL and ENDLOCAL.
After studying all those help and web pages it should be no problem anymore to understand this code:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "DataPath=D:\MeasurementData\%~n0"
for /L %%N in (1,1,5) do (
set "DateFile=%DataPath%%%N"
echo !DateFile!
pause
C:\TomoK.exe "!DateFile!" "D:\MParameter.mff" "D:\MParameter.mcf"
pause
)
endlocal
I don't know why command START was used to run the executable TomoK.exe and therefore removed it.
However, the batch file could be also written without delayed expansion because the environment variable DataFile is not really needed in body of loop at all. And the entire batch code above can be optimized to a single command line in batch file:
#for /L %%N in (1,1,5) do #C:\TomoK.exe "D:\MeasurementData\%~n0%%N" "D:\MParameter.mff" "D:\MParameter.mcf"
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.
echo /?
endlocal /?
for /?
pause /?
set /?
setlocal /?
start /?

Why is string comparison after prompting user for a string/option not working as expected?

Is this the proper way to write these lines of batch code with the exceptions of spaces and unneeded percent signs?
:name
cls
echo now that we've got your color figured out, what about your name?
echo simply type the name you want for your character into the space below
echo (6 char max)
echo.
set /p %player% =
cls
echo so you want your name to be %player% ?
echo.
echo 1) yes
echo 2) no
set /p %namechoice% =
if %namechoice% == 1 goto check
if %namechoice% == 2 goto name
:check
if /I %player% == %username% (goto gamestart) else goto suprise
:suprise
The player name is not output after batch user entered it.
And the string comparisons with check and name are also not working.
The command line if %namechoice% == 1 goto check results in break of batch file execution with error message:
goto was unexpected at this time.
The main mistake is a simple syntax issue:
Environment variables are defined with just specifying the variable name without percent signs and with no space character before the equal sign.
So wrong is
set /p %player% =
set /p %namechoice% =
because those two lines are expanded during preprocessing phase before really executing the command SET to
set /p =
set /p =
in case of environment variables player and namechoice are not already defined. See Why is no string output with 'echo %var%' after using 'set var = text' on command line? for details about how to define an environment variable right. It explains also why the space character left to equal sign on variable definition becomes part of the variable name which is nearly always unwanted by batch file writer.
Such simple syntax issues can be easily seen on running a batch file without #echo off at top of the batch file or with this line modified to #echo on or commented out with ::#echo off (invalid label) or rem #echo off (remark command) from within a command prompt window by entering name of the batch file with full path in double quotes instead of double clicking on the batch file.
What makes the difference?
With #echo off the command lines are not printed into the console window after preprocessing (expanding environment variables) before really executing them. This is the wanted behavior when batch file development finished. But during development and testing of a batch file it is definitely better to get displayed what is really executed by Windows command interpreter to find coding mistakes.
On double clicking a batch file cmd.exe is started to execute the batch file with option /C for closing the console window automatically when batch file execution terminated independent on success or error of execution. This makes it not possible to see for example syntax errors output by Windows command interpreter which result in an immediate exit of batch file execution. Therefore it is advisable during batch file development to run it from within a manually opened command prompt window as in this case cmd.exe is started with option /K to keep the console window open even after batch processing finished, except the batch file uses command exit without parameter /B. This makes it possible to see also the error message of an error which caused an unexpected exit of batch processing.
Later when batch file works as expected, the first line can be #echo off again and of course the batch file can be started with a double click. But during batch file development it is definitely better to always run the batch file from within a command prompt window. The up/down arrow keys can be used to scroll through the list of entered strings which makes it also possible to re-enter for example the player name easily again.
Here is the batch code rewritten with several improvements and comments:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Define a too long player name before prompting the user for the player
rem name. This too long player name is kept in case of user hits just the
rem key RETURN or ENTER without entering anything at all. Then test for
rem entered name has not more than 6 characters. Delayed expansion is used
rem as the user could enter characters like " ! % ... which would in further
rem batch code execution result in exiting batch processing because of syntax
rem error or in unexpected behavior on referencing player name with expansion
rem before running the command.
:PromptForName
cls
echo Now that we've got your color figured out, what about your name?
echo Simply type the name you want for your character into the space
echo below (6 char max).
echo/
set "Player=No name entered"
set /P "Player=Player name: "
if not "!Player:~6!" == "" goto PromptForName
echo/
echo/
echo 1) yes
echo 2) no
echo/
choice /C:12 /N "So you want your name to be !player!? "
if errorlevel 2 goto PromptForName
if /I "!player!" == "%USERNAME%" goto GameStart
echo Surprise
endlocal
goto :EOF
:GameStart
echo/
echo Okay !Player!, let's play^^!
rem Wait 3 seconds using PING instead of TIMEOUT before exiting the
rem batch file because the command TIMEOUT does not exist on Windows XP.
%SystemRoot%\System32\ping.exe 127.0.0.1 -n 4 >nul
endlocal
The comment at top explains why the environment variable Player is defined with value No name entered. The batch user has the freedom to hit just RETURN or ENTER without entering anything at all or hits by mistake one of those 2 keys before entering a name. In this case the environment variable Player is either still not defined if not defined before, or it keeps its current value if already defined before. It is not good if the user enters nothing and the environment variable Player is not defined in this case. Therefore the player name is predefined with an invalid name.
The length of the entered player name is also tested on being too long.
And the string entered by the user could contain batch syntax critical characters like a double quote, a percent sign, a redirection operator character (angle bracket, pipe), an ampersand, or with delayed expansion enabled an exclamation mark. To prevent an exit of batch processing caused by a syntax error by entered player name on using environment variable expansion before command line execution, the environment variable Player is referenced everywhere with usage of delayed expansion enabled at top of the batch file.
For printing a blank line it is better to use echo/ instead of echo. because echo. could fail and is a little bit slower because of Windows command interpreter searches for a file matching the pattern echo.* as documented in DosTips forum article ECHO. FAILS to give text or blank line - Instead use ECHO/.
The command CHOICE is much better than set /P VariableName=Prompt text if the user has to enter specific keys. The command CHOICE does not allow that the user enters something not wanted by batch file writer and is therefore much safer for a choice menu.
The account name of current user referenced with %USERNAME% could contain also a space character. Therefore it is highly recommended to enclose the entire string containing %USERNAME% always in double quotes.
"%USERNAME%" on right side of a string comparison requires that the string on left side is also enclosed in double quotes because command IF compares the two strings with including the double quotes.
For that reason the condition
if /I !player! == "%USERNAME%"
would be only true if the batch file user would have entered the player name with double quotes which is very unlikely. The double quotes must be also used on left side.
The number of space characters around the two compared strings enclosed in double quotes or not enclosed in double quotes does not matter.
Executing in a command prompt window the following batch file
#echo on
#setlocal EnableExtensions EnableDelayedExpansion
#set "Player=<|>"
if /I "!Player!"=="%SystemRoot%" echo Strings are equal.
if /I "!Player!" == "%WinDir%" echo Strings are equal.
if /I "!Player!" == "%Player%" echo Strings are equal.
if /I "!Player!"== "!Player!" echo Strings are equal.
if /I !Player! == !Player! echo Strings are equal.
#endlocal
results in the output
if /I "!Player!" == "C:\WINDOWS" echo Strings are equal.
if /I "!Player!" == "C:\WINDOWS" echo Strings are equal.
if /I "!Player!" == "<|>" echo Strings are equal.
Strings are equal.
if /I "!Player!" == "!Player!" echo Strings are equal.
Strings are equal.
if /I !Player! == !Player! echo Strings are equal.
Strings are equal.
It can be seen that the space characters around comparison operator == do not matter on execution of command IF. The Windows command processor formats the command lines pretty before executing the IF commands.
But a space character in a string to compare requires the usage of double quotes because otherwise an exit of batch processing occurs most likely because of a syntax error on batch file execution.
Note: The equal operator == of command IF is handled different than the assignment operator = of command SET. Don't mix them.
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.
choice /?
cls /?
echo /?
endlocal /?
goto /?
if /?
ping /?
rem /?
set /?
setlocal /?
And see also the Microsoft article Using command redirection operators for an explanation of >nul.

Resources