I'm making a batch program that I want to stop Midway. Like I only want it to execute the other commands when they are called like :Command. Is there a way I can do this? I am not looking for a pause, I want it to not play the other commands that are below. I want it to just stop the code in its tracks. So it doesn't play any commands until they are called. Example below:
#echo off
:Talk
Echo DONT DO THIS PART UNTIL CALLED
:NoName
echo Going to Talk
goto :Talk
the normal way to do this is exit or goto :eof. Also goto is helpful:
using goto :eof(means: "go to end of the script"):
set /p "x=Enter a command: "
if /i "%x%"="talk" call talk
goto :eof
echo this line will never be reached
:talk
echo going to talk
goto :eof
:listen
echo listening part
goto :eof
using exit:
set /p "x=Enter a command: "
if /i "%x%"="talk" call talk
exit /b
echo this line will never be reached
:talk
echo going to talk
goto :eof
using goto:
:input
set /p "x=Enter a command: "
if /i "%x%"="talk" call talk
goto :input
echo this line will never be reached
:talk
echo going to talk
goto :eof
In other words: end each of your called "Subroutines" with goto :eof
Related
So I currently creating a program that hide a files and moving it to other places, and to retrieve the file you need to put the password. But i found a problem where when i only press ENTER and not putting a password, the batch program closed. I wanted to make it so that when you press ENTER or not putting a password it says "Please enter the password!" until it gets what it wanted. (to be honest this is just something that i googled and copy paste, and change it a little)
Additional question, is it fine to use set /p "something=>" instead of set /p something=
Here is the commands and codes that i used.
I know that this is complicted and might be the worst thing to write.
#ECHO OFF
title unlock the stuff
if EXIST SecretCodes goto CONFIRM
if NOT EXIST SecretCodes goto CONFIRMATION
:CONFIRM
echo are you sure you want to Lock the stuff?(Y/N)
set /p "cho=>"
if %cho%==Y goto LOCK
if %cho%==y goto LOCK
if %cho%==n goto END
if %cho%==N goto END
echo excuse me?
goto CONFIRM
:LOCK
move /-Y C:\Users\MyName\Desktop\SecretCodes C:\Users\MyName\AppData\Roaming\Hidden
attrib +H +S C:\Users\MyName\AppData\Roaming\Hidden\SecretCodes
echo Secret is locked!! o7
pause
goto END
:UNLOCK
title Unlock
echo Please enter the password!
set /p "pass=>"
if NOT %pass%== passwordispassword goto FAIL
move /-Y C:\Users\MyName\AppData\Roaming\Hidden\SecretCodes C:\Users\MyName\Desktop
echo the secret has been revealed!
pause
goto END
:FAIL
title Unlock
set /p "pass=>"
if NOT %pass%== passwordispassword goto END
move /-Y C:\Users\MyName\AppData\Roaming\Hidden\SecretCodes C:\Users\MyName\Desktop
echo the secret has been revealed!
goto END
:CONFIRMATION
echo are you sure you want to Unlock the secrets?(Y/N)
set /p "choo=>"
if %choo%==Y goto UNHIDE
if %choo%==y goto UNHIDE
if %choo%==n goto END
if %choo%==N goto END
echo excuse me?
goto CONFIRMATION
:UNHIDE
attrib -H -S C:\Users\MyName\AppData\Roaming\Hidden\SecretCodes
goto UNLOCK
to makes things more clearer, in the codes that i write :
:CONFIRM
echo are you sure you want to Lock the stuff?(Y/N)
set /p "cho=>"
if %cho%==Y go to LOCK
if %cho%==y goto LOCK
if %cho%==n goto END
if %cho%==N goto END
echo excuse me?
goto CONFIRM
, will make me repeat the command if i put the wrong input for example i type E and then enter. It will say "excuse me?" and then asking again "are you sure you want to Lock the stuff?(Y/N)", the problem that i'm getting is when i put nothing (press Enter immediately...). when i put nothing into it, the cmd will close.
So going back to question number 1, is there a way to prevent cmd closing from pressing the enter button and not put any password on the input?
This optimized batch file code should work as expected by you.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
if not exist "%USERPROFILE%\Desktop\SecretCodes" goto PromptUnlock
:PromptLock
title Lock the stuff
%SystemRoot%\System32\choice.exe /C YN /N /M "Are you sure you want to LOCK the stuff? (Y/N)"
if errorlevel 2 goto EndBatch
move /-Y "%USERPROFILE%\Desktop\SecretCodes" "%APPDATA%\Hidden"
%SystemRoot%\System32\attrib.exe +H +S "%APPDATA%\Hidden\SecretCodes"
echo/
echo Secret is locked!! o7
echo/
pause
goto EndBatch
:PromptUnlock
title Unlock the stuff
%SystemRoot%\System32\choice.exe /C YN /N /M "Are you sure you want to UNLOCK the stuff? (Y/N)"
if errorlevel 2 goto EndBatch
%SystemRoot%\System32\attrib.exe -H -S "%APPDATA%\Hidden\SecretCodes"
:PromptPassword
set "pass="
set /P "pass=Please enter the password: "
rem Has the user entered a string at all?
if not defined pass goto PromptPassword
rem Remove all double quotes from entered password string for a safe
rem string comparison below. Password cannot contain character " at all.
set "pass=%pass:"=%"
if not "%pass%" == "passwordispassword" goto PromptPassword
move /-Y "%APPDATA%\Hidden\SecretCodes" "%USERPROFILE%\Desktop"
echo/
echo The secret has been revealed!
echo/
pause
:EndBatch
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 /?
move /?
pause /?
rem /?
set /?
setlocal /?
title /?
See also: How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
(This is my first post here, so bear with me)
Can you show the last user-input in a batch file? I'm gonna try to keep it simple here.
#echo off
:menu
echo Type 1 to proceed.
set /p example=
if "%example%" == "1" GOTO :proceed
GOTO :error
:proceed
pause
:error
cls
echo You wrote (last user input), that's not correct.
timeout 30
GOTO :menu
I know that I could replace the (last user input) with %example%, but then I'd have to make custom error messages for every category, and there are about 50 of them. It'd be easier with a last input command.
By the way, I've taught myself everything that I know about batch, so my example probably has major issues right now, but it works somehow.
You could centralize all user input into a function (user_input)
:menu1
echo Type 1 to proceed.
call :userInput example
if "%example%" == "1" GOTO :proceed
GOTO :error
:menu2
echo Type 42 to proceed.
call :userInput answer
if "%answer%" == "42" GOTO :proceed
GOTO :error
:userInput
set /p LAST_INPUT=
set "%1=%LAST_INPUT%"
exit /b
:proceed
pause
:error
cls
echo You wrote "%LAST_INPUT%", that's not correct.
timeout 30
GOTO :menu
I don't know how to do it without temp file. TO get the things written int the console you need the doskey /history (this will skip the running of the script itself):
#echo off
setlocal enableDelayedExpansion
set "last="
set "but_last="
doskey /history > log.txt
for /f "tokens=* delims=" %%# in (log.txt) do (
set "but_last=!last!"
set "last=%%#"
)
echo "%but_last%"
del /s /q log.txt >nul 2>nul
I can't fix this I want to be able to write anything as a response which works with
:being
but not
:Fap
here is my code
:begin
cls
echo You wake up and realize you are never going to amount to anything, oh well, might as well get on with your worthless life
echo fap or vidya games
echo.
set /p input=
if /i "%input%"=="Fap" goto Fap
if /i "%input%"=="Vidya games" goto vidya games
if /i "%input%"=="vidya" goto vidya games
if not "%input%"=="Fap"/"vidya"/"Vidya games" goto begin
:Fap
cls
echo Since you can't get a girl you decide to fantize about the girl of your dreams so you download some watamote doujins after a mixture of crying and masterbaiting you decide to change to mood
echo vidya or sleep
echo.
set /p input=
if /i "%input%"=="vidya" goto vidya fap
if /i "%input%"=="sleep" goto sleep
if not "%input%"=="vidya"/"sleep" goto Fap
Labels in batch scripts are marked by a colon like :begin. Same approach is used when redirecting to a certain label from IF, FOR or similar statement. So, edit your script by following this example:
if /i "%input%"=="Fap" (goto :Fap
) else if /i "%input%"=="Vidya" (goto :Vidya_games
) else (goto :begin)
Instead of those many ifs, you can check, if a label exists and if yes, jump to it:
If you have several questions with different destinations, you can name your labels accordingly:
#echo off
:loop
echo fap or vidya games
set /p "label=Command: "
findstr /b /i ":Q1-%label%" "%~f0" && goto :Q1-%label%
REM previous line checks, if the label exists and if yes, jumps to it
echo no such command: %label% & goto :loop
:Q1-fap
echo reached Question1 label one.
goto :eof
:Q1-vidya
echo reached Question1 label two.
goto :eof
Some notes:
labels are single word only. Everything after the first space is ignored.
findstr /i makes it insensitive to capitalization.
/b searches for lines that start with the string.
&& means "if previous command (findstr here) was successful, then"
%~f0 is the name of your batchfile.
This goes to Q1-vidya when you enter vidya, Vidya, VIDYa, vidya Games or Vidya anything.
I've been reading how to avoid spaghetti code in batch files.
In the example of what spaghetti code is, I realized that the batch file that I use when I logon almost fits this example. Could someone please help me make my batch file not have spaghetti code?
#ECHO OFF
CLS
:MENU
echo Welcome %USERNAME%
echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit
SET /P M=Please Enter Selection, then Press Enter:
IF %M%==1 GOTO StarKeePass
IF %M%==2 GOTO Backup
IF %M%==3 GOTO FireFox
IF %M%==4 GOTO :EOF
GOTO MENU
:StarKeePass
SET keePass="%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
SET kdb="%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"
echo I'll start KeePass for You
START "" %keePass% %kdb%
GOTO MENU
:Backup
SET backup="%USERPROFILE%\backup.bat"
call %backup%
GOTO MENU
:FireFox
cd "C:\Program Files (x86)\Mozilla Firefox\"
start firefox.exe
GOTO MENU
In this case, if you want to use subroutines you should do this:
#ECHO OFF
CLS
:MENU
echo Welcome %USERNAME%
echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit
SET /P M=Please Enter Selection, then Press Enter:
IF %M%==1 CALL :StartKeePass
IF %M%==2 CALL :Backup
IF %M%==3 CALL :FireFox
IF %M%==4 GOTO :EOF
GOTO MENU
:StartKeePass
SET "keePass=%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
SET "kdb=%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"
echo I'll start KeePass for You
START "" %keePass% %kdb%
GOTO :EOF
:Backup
SET "backup=%USERPROFILE%\backup.bat"
call %backup%
GOTO :EOF
:FireFox
cd "C:\Program Files (x86)\Mozilla Firefox\"
start firefox.exe
GOTO :EOF
Note that I changed a few things. Instead of goto... goto menu, you should use call :label goto :eof/ exit /b. Besides that, you had a spelling error StartKeePass, and instead of set variable="value", it's better to use set "variable=value". This will also accept spaces in the value, but it won't add quotes to your variable
Next time you should probably post this to code review, because these things aren't really errors
If you wanted to remove gotos altogether, you can simply call the script again to keep using it. Also, look into the choice command if you're using a version of Windows later than XP, since it will eliminate the need to check if the user entered invalid input.
#echo off
cls
echo Welcome %USERNAME%
echo 1 - Start KeePass
echo 2 - Backup
echo 3 - FireFox
echo 4 - Exit
choice /C:1234 /M "Please enter your selection: " /N
:: The first option listed by choice's /C option will return an errorlevel value of 1, the second 2, and so on
if %errorlevel% equ 1 (
SET keePass="%USERPROFILE%\KeePass\KeePass-2.30\KeePass.exe"
SET kdb="%USERPROFILE%\KeePass\PasswordDatabase\PasswordDatabase.kdbx"
echo I'll start KeePass for You
START "" %keePass% %kdb%
)
:: I've converted these to one-liners simply for personal preference.
:: You can keep these the way you had them if you put them inside of parentheses like with option 1.
if %errorlevel% equ 2 call "%USERPROFILE%\backup.bat"
if %errorlevel% equ 3 start "" "C:\Program Files (x86)\Mozilla Firefox\firefox.exe"
if %errorlevel% equ 4 exit /b
:: Calls this script again, simulating a goto :MENU
:: Personally, I'd stick with a label and a goto in this instance,
:: but this is how you could do it if you don't want to use goto at all
call %0
If each choice the user can make is fairly simple (i.e. it can be simplified to one or two commands), you might want to code this way; otherwise, definitely use subroutines like Dennis suggested.
My take on organizing this, added a reset to m variable, allowed some accidental input to be dealt with, and made it all checked in one block of code.
Nothing wrong with 'Dennis van Gils' answer, figured i would show you a different approach.
#echo off
setlocal enableDelayedExpansion
:menu
set "m="
cls
echo/Welcome !username!
echo/
echo/1 - Start keepass
echo/2 - Backup
echo/3 - Firefox
echo/4 - Exit
echo/
set /p "m=Please enter selection, then press enter:"
if not defined m (
cls
echo/Error: Empty input.
pause
) else (
if "!m!" equ "1" (
set "keepass=!userprofile!\keepass\keepass-2.30\keepass.exe"
set "kdb=!userprofile!\keepass\passworddatabase\passworddatabase.kdbx"
echo/I'll start keepass for you
start "" !keepass! !kdb!
) else (
if "!m!" equ "2" (
set "backup=!userprofile!\backup.bat"
call !backup!
) else (
if "!m!" equ "3" (
cd "c:\program files (x86)\mozilla firefox\"
start firefox.exe
) else (
if "!m!" equ "4" (
goto :eof
) else (
cls
echo/Error: ["!m!"] not recognized.
pause
)
)
)
)
)
goto :menu
Note: echo/ is used as a habit, as echo: and echo\ i mistake for parts of a file path/url, and echo. is so painstakingly noted for its longer command time.
Also, i prefer using ! over % along with setlocal enableDelayedExpansion by pure preference, and ease of block coding.
I'm making a batch file with need to have two inputs as follow:
echo What's the name of your two brothers
set/p input1=
set/p input2=
Now what do I want is something like this:
if %input1==anything and if %input2%==OtherThing goto Continue
But I don't know how to do it right. Please NEED HELP
Thnks.
if "%input1%" EQU "anything" if "%input2%" EQU "OtherThing" goto :Continue
if "%input1%/%input2%" == "anything/OtherThing" goto Continue
Try like this :
#echo off
echo What's the name of your two brothers
set /p "input1=Brother 1 :"
set /p "input2=Brother 2 :"
if /i "%input1%"=="anything" (
if /i "%input2%"=="OtherThing" goto Continue
echo One brother matched
pause
exit/b)
echo No Brother Matched
pause
exit/b
:continue
echo Two Brother matched
pause
If you're trying to execute the GOTO command only if the first AND the second IF statements are true, use this:
if %input1%==anything && if %input2%==OtherThing goto continue
The && tells the program to execute the command after it only if the one before it is true.
You could also add some other features to the program, like ignoring the order that you enter the brothers. To do that, use this:
if %input1%==anything && if %input2%==OtherThing goto continue
if %input1%==OtherThing && if %input2%==anything goto continue
echo Your brothers do not match description etc...
pause
exit
You could also use case insensitive comparing like this:
if /I %input1%==anything && if /I %input2%==OtherThing goto continue
There are alot of other things possible to embelish your program. If you need more help with a certain command, open cmd.exe and type a command with the /? switch.
Update:
Sorry my first answer didn't work, but I have come up with the start of a new .bat program that should do the job. If this action is the first action of your program, copy and paste this code at the very beginning of your program:
#echo off
echo Enter the name of your first brother.
set /P input1=
cls
echo Enter the name of your second brother.
set /P input2=
if %input1%==anything goto %input1%
if not %input1%==OtherThing goto checkinput2
goto %input1%
:anything
if %input2%==OtherThing (goto continue) else cls & echo Only one brother matched. & echo. & pause & exit /b
:OtherThing
if %input2%==anything (goto continue) else cls & echo Only one brother matched. & echo. & pause & exit /b
:checkinput2
if %input2%==OtherThing cls & echo Only one brother matched. & echo. & pause & exit /b
if %input2%==anything cls & echo Only one brother matched. & echo. & pause & exit /b
cls
echo No brothers matched.
echo.
pause
exit /b
:continue
"the rest of your program here"
Wherever you see "anything" replace it with the name of one brother. Wherever you see "OtherThing" replace it with the name of the other brother. The names will be case senitive. Where you see "the rest of your program here", that is your :continue statement. Just continue your program from this line.
If this action is somewhere in the middle of your program, replace the first line, #echo off, with cls to clear whatever was on the screen from the other program commands.
I hope this works well for you.