Having trouble getting this CHOICE script to work. Can anyone provide any insight?
#echo off
CHOICE /C:IRCQSH /T 10 /N /M "Waiting with choice..." /D H
IF ERRORLEVEL 0 ECHO "Default choice: Health"
IF ERRORLEVEL 1 ECHO "Install"
IF ERRORLEVEL 2 ECHO "Remove"
IF ERRORLEVEL 3 ECHO "Console"
IF ERRORLEVEL 4 ECHO "Quit"
IF ERRORLEVEL 5 ECHO "Start"
IF ERRORLEVEL 6 ECHO "Health"
pause
You need to change your syntax to treat ERRORLEVEL as a variable, and use the CMD equality statements, such as:
IF %ERRORLEVEL% EQU 0 ECHO "Default choice: Health"
IF %ERRORLEVEL% EQU 1 ECHO "Install"
IF %ERRORLEVEL% EQU 2 ECHO "Remove"
IF %ERRORLEVEL% EQU 3 ECHO "Console"
IF %ERRORLEVEL% EQU 4 ECHO "Quit"
IF %ERRORLEVEL% EQU 5 ECHO "Start"
IF %ERRORLEVEL% EQU 6 ECHO "Health"
The reason your code is failing is, taken from here:
IF ERRORLEVEL n statements should be read as IF Errorlevel >= number
i.e.
IF ERRORLEVEL 0 will return TRUE when the errorlevel is 64
A couple points here:
The default choice does NOT return an ERRORLEVEL of zero, but the number of the choice selected. In your case, that is H, the default is equal to press H with an ERRORLEVEL of 6
The right way to take the value of ERRORLEVEL is enclosing it in percents and use the EQU comparison, as LittleBobbyTables said in his answer. However, there are other ways to achieve the same result.
The IF ERRORLEVEL Number Command test if the errorlevel value is Greater or Equal than the given number, so you may also use this form:
.
#echo off
CHOICE /C:IRCQSH /T 10 /N /M "Waiting with choice..." /D H
FOR %%E IN (6 5 4 3 2 1) DO IF ERRORLEVEL %%E GOTO LABEL-%%E
:LABEL-1
ECHO "Install"
GOTO CONTINUE
:LABEL-2
ECHO "Remove"
GOTO CONTINUE
:LABEL-3
ECHO "Console"
GOTO CONTINUE
:LABEL-4
ECHO "Quit"
GOTO CONTINUE
:LABEL-5
ECHO "Start"
GOTO CONTINUE
:LABEL-6
ECHO "Health"
:CONTINUE
pause
Perhaps the simplest way to achieve the same thing is defining an array and show the appropriate element using the errorlevel value as index:
.
#echo off
setlocal EnableDelayedExpansion
rem Create an array with the desired messages (selected by numeric index)
set index=0
for %%a in ("Install" "Remove" "Console" "Quit" "Start" "Health") do (
set /A index+=1
set elem[!index!]=%%a
)
CHOICE /C:IRCQSH /T 10 /N /M "Waiting with choice..." /D H
echo !elem[%ERRORLEVEL%]!
pause
For a further description of Batch arrays, see: Arrays, linked lists and other data structures in cmd.exe (batch) script
Related
I want to put a 30s time limit for the :choice Y/N/P and after the time is up goto :start
The code I have need help for the timeing thing
#echo off
:start
echo AmishCraft will start
TIMEOUT /T 5
echo (%time%)
java -Xms2048M -Xmx4096M -jar server.jar
call C:\Program Files (x86)\Common Files\Oracle\Java\javapath\java.exe
ping 1.1.1.1 -n 1 -w 3000 >nul
:choice
set /P a=do you want to restart? Yes No Pause [Y/N/P]?
if /I "%a%" EQU "Y" goto :restart
if /I "%a%" EQU "N" goto :stop
if /I "%a%" EQU "P" goto :pause
goto :start
:restart
cls
echo server will restart
cls
goto :start
:stop
cls
echo closing server
TIMEOUT /T 5
exit
cls
echo server is paused
:pause
:choice
set /P a=do you want start? Restart Stop [R/S]?
if /I "%a%" EQU "R" goto :restart
if /I "%a%" EQU "S" goto :stop
goto :start
pause
/T is the timeout switch for choice.
/D is the switch to define the default errorlevel / option to set if the
time Elapses.
Example:
CHOICE /T 5 /N /C 1234 /M "Select Option 1,2,3 or 4" /D 1
Applies a timeout of 5 seconds, with the errorlevel being set to option 1, equal to errorlevel 1 in this instance.
/N Hides the default Choice Prompt String.
/M Allows you to Define your own Prompt string
/C Allows alphanumerical characters to be defined as Choice options
Note:
Errorlevel is Set from Left to Right with regards to listed options.
After the Choice Command Errorlevel Needs to be Assessed From Highest to lowest
OR
Used Directly; Such as in a Goto :LabelName%errorlevel% Command
* Response to comment *
CHOICE /C 123 /T Timeout 25 /D goto :start /M 1 choice menu 25s
IF %ERRORLEVEL% EQU 1 goto :choice1
There are multiple errors in the above.
/T Timeout 25 should be: /T 25
Timeout is implicit in the /T switch and does NOT form a part of correct usage of the choice command.
/D goto :start should be: /D 1 OR /D 2 OR /D 3
Only the defined /C options should be used following the /D switch
/M 1 choice menu 25s is incorrect.
The prompt after /M should be encased in Doublequotes: "[1] Option 1. [2] Option 2. [3] Option 3."
Errorlevel Assessment should be done on the Line After the CHOICE Command.
Again, to be clear, Assesment should be done from Highest to Lowest. When errorlevel is Assessed following Choice it is actually interpreted as If ERRORLEVEL GTR n , Despite being scripted Using If ERRORLEVEL n
An example of the Correct usage of all of the above:
#echo off
:menu
cls
CHOICE /N /T 25 /C 123 /M "[1] Option 1. [2] Option 2. [3] Start." /D 3
IF ERRORLEVEL 3 (
GOTO :start
) else (
GOTO :choice%errorlevel%
)
:start
ECHO( You are at the start
Pause
GOTO :menu
:choice1
ECHO( You are at option 1
Pause
GOTO :menu
:choice2
ECHO( You are at option 2
Pause
GOTO :menu
Okay I am trying to ask the user the below question in a batch file but don't think that I am entering the correct choice command.
echo Would you like to know the time? (Y/N)
CHOICE /C YN /N
GOTO OPTION-%ERRORLEVEL%
:OPTION-Y Yes
echo %time%
goto cont
:OPTION-N No
:cont
P.S today is my first day of the couse so I am a newbie, please don't judge.
Because %errorlevel% is a number not Y or N
Your labels should be :OPTION-1 and :OPTION-2:
#echo off
echo Would you like to know the time? (Y/N)
CHOICE /C YN /N
GOTO OPTION-%ERRORLEVEL%
:OPTION-1
echo %time%
goto cont
:OPTION-2
:cont
Here is another example so you can understand how it assigns the %errorlevel% number to the key you selected.
#echo off
:start
cls
CHOICE /C YNM /N /M "Should I display the Time? Select (Yes (Y) No (N) or Maybe (M))"
if %errorlevel%==1 echo %time%
if %errorlevel%==2 echo Ok, I won't then
if %errorlevel%==3 echo it is fine, I will ask again in 10 seconds & timeout /T 10 & goto :start
Here you can see it assigns the first key to %errorlevel% 1, the second key to %errorlevel% 2 and third key to %errorlevel% 3 etc.
CHOICE does not return the selected key as %ERRORLEVEL%, it returns the index of the selected key - that is, for CHOICE /C YN, if you select Y, %ERRORLEVEL% will be 1; for N, it will be 2. See SS64 on CHOICE.
You also have to be careful about the order that you test %ERRORLEVEL%; the standard construct IF ERRORLEVEL n ... is actually testing to see whether %ERRORLEVEL% is equal to or greater than n. See SS64 on ERRORLEVEL.
You could also reduce all of your provided snippet to two lines, (continuing your script beneath them as necessary):
Choice /M "Would you like to know the time"
If Not ErrorLevel 2 Echo %TIME% & Timeout 3 >Nul
I am a dabbler in batch files so my knowledge is limited to my experiences. What I am trying to do is limit the "Y or N" inputs to just that Y or N. Right now you can put anything in the fields and the code progresses. What I am attempting to do is create a hotspot using a batch file. I have yet to figure out how to "save" the created network but that isn't really an issue.
I have included what I have, the lines being the start and finish, If anyone happens to see anything that can be improved upon or made less bulky feel free to comment.
#echo off
:: BatchGotAdmin
:-------------------------------------
REM --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
:--------------------------------------
#echo off
:SSID
set /P inputA="Input desired Network SSID:"
echo.
set /P c=Is %inputA% correct? [Y/N]?
echo.
if /I "%c%" EQU "Y" goto :PSWD
if /I "%c%" EQU "N" goto :SSID
:PSWD
set /P inputB="Input desired 8 to 63 character Network Password:"
echo.
set /P c=Is %inputB% correct? [Y/N]?
echo.
if /I "%c%" EQU "Y" goto :SETUP
if /I "%c%" EQU "N" goto :PSWD
:SETUP
netsh wlan set hostednetwork mode=allow ssid=%inputA% key=%inputB% >NUL
#echo Creating Network...
echo.
timeout /t 5 /nobreak > NUL
#echo Network Created!
echo.
timeout /t 1 /nobreak > NUL
set /P c=Would you like to start your new Network? [Press "Y" to continue/Press "N" to abort]
if /I "%c%" EQU "Y" goto :START
if /I "%c%" EQU "N" goto :BYE
:START
netsh wlan start hostednetwork
timeout /t 5 /nobreak > NUL
#echo Your Network has started!
pause
:BYE
Exit
Instead of using set /p, use the choice command. I, personally, would use:
choice /m Correct?
if %errorlevel% equ 1 goto PSWD
if %errorlevel% equ 2 goto SSID
This will display: Continue? [Y/N]?. If the hit y, it will go to :PSWD. If they hit n, it will go to :SSID.
The help section of the choice command (brought up in Command Prompt by choice /?)
CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]
Description:
This tool allows users to select one item from a list
of choices and returns the index of the selected choice.
Parameter List:
/C choices Specifies the list of choices to be created.
Default list is "YN".
/N Hides the list of choices in the prompt.
The message before the prompt is displayed
and the choices are still enabled.
/CS Enables case-sensitive choices to be selected.
By default, the utility is case-insensitive.
/T timeout The number of seconds to pause before a default
choice is made. Acceptable values are from 0 to
9999. If 0 is specified, there will be no pause
and the default choice is selected.
/D choice Specifies the default choice after nnnn seconds.
Character must be in the set of choices specified
by /C option and must also specify nnnn with /T.
/M text Specifies the message to be displayed before
the prompt. If not specified, the utility
displays only a prompt.
/? Displays this help message.
NOTE:
The ERRORLEVEL environment variable is set to the index of the
key that was selected from the set of choices. The first choice
listed returns a value of 1, the second a value of 2, and so on.
If the user presses a key that is not a valid choice, the tool
sounds a warning beep. If tool detects an error condition,
it returns an ERRORLEVEL value of 255. If the user presses
CTRL+BREAK or CTRL+C, the tool returns an ERRORLEVEL value
of 0. When you use ERRORLEVEL parameters in a batch program, list
them in decreasing order.
Examples:
CHOICE /?
CHOICE /C YNC /M "Press Y for Yes, N for No or C for Cancel."
CHOICE /T 10 /C ync /CS /D y
CHOICE /C ab /M "Select a for option 1 and b for option 2."
CHOICE /C ab /N /M "Select a for option 1 and b for option 2."
I do something like this:
echo 1-exit
echo 2-about
echo 3-play
choice /c 123 >nul
if errorlevel 1 goto exit
if errorlevel 2 goto about
if errorlevel 3 goto play
:play
blah
:about
blah
:exit
cls
If I select the "play" option, it exits. How do I prevent this from happening?
The if errorlevel expression evaluates to true if actual error level returned by choice is greater or equal to given value. So if you hit 3, the first if expression is true and script terminates. Call help if for more information.
There are two simple workarounds.
First one (better) - replace if errorlevel expression with actual comparision of %ERRORLEVEL% system variable with a given value:
if "%ERRORLEVEL%" == "1" goto exit
if "%ERRORLEVEL%" == "2" goto about
if "%ERRORLEVEL%" == "3" goto play
Second one - change order of comparisions:
if errorlevel 3 goto play
if errorlevel 2 goto about
if errorlevel 1 goto exit
The easiest way to solve this problem is to use the %errorlevel% value to directly go to the desired label:
echo 1-exit
echo 2-about
echo 3-play
choice /c 123 >nul
goto option-%errorlevel%
:option-1
rem play
blah
:option-2
rem about
blah
:option-3
exit
cls
Just stumbled into a weird thing with %ERRORLEVEL% and wanted to see if anyone knows why and if there's a way to fix it. Essentially, it seems as if commands executed inside if statements don't set the %ERRORLEVEL% variable. The ERRORLEVEL (as in IF ERRORLEVEL 1, which is different from IF %ERRORLEVEL% EQU 1 ) check seems to still work fine though, so I can probably work around it, but it would still be nice to be able to print the error level. For debugging or whatever.
#echo off
Set TESTVAR=1
tasklist | find /I "IsntRunning.exe" > NUL
echo OUTSIDE_IF %ERRORLEVEL%
ThisWillSetErrorLevelTo9009ieNotRecognizedCommand
tasklist | find /I "IsntRunning.exe" > NUL
echo OUTSIDE_IF %ERRORLEVEL%
ThisWillSetErrorLevelTo9009ieNotRecognizedCommand
IF %TESTVAR% EQU 1 (
Set ERRORLEVEL=
tasklist | find /I "IsntRunning.exe" > NUL
echo INSIDE_IF ERRORLEVEL %ERRORLEVEL%
IF ERRORLEVEL 1 (
echo INSIDE_IF2 ERRORLEVEL GREQ 1 %ERRORLEVEL%
)
IF ERRORLEVEL 2 (
echo INSIDE_IF2 ERRORLEVEL GREQ 2 %ERRORLEVEL%
)
IF ERRORLEVEL 3 (
echo INSIDE_IF2 ERRORLEVEL GREQ 3 %ERRORLEVEL%
)
)
tasklist | find /I "IsntRunning.exe" > NUL
echo OUTSIDE_IF ERRORLEVEL %ERRORLEVEL%
#echo on
Putting that in a batch file and running it produces this output:
C:\Users\username\Documents\work>test.bat
OUTSIDE_IF 1
'ThisWillSetErrorLevelTo9009ieNotRecognizedCommand' is not recognized as an internal or external command,
operable program or batch file.
OUTSIDE_IF 1
'ThisWillSetErrorLevelTo9009ieNotRecognizedCommand' is not recognized as an internal or external command,
operable program or batch file.
INSIDE_IF ERRORLEVEL 9009
INSIDE_IF2 ERRORLEVEL GREQ 1 9009
OUTSIDE_IF ERRORLEVEL 1
Relevant articles:
http://blogs.msdn.com/b/oldnewthing/archive/2008/09/26/8965755.aspx
http://support.microsoft.com/kb/69576
Try using setlocal enabledelayedexpansion at the start of your batch file, and !ERRORLEVEL! inside your IF. This seems to work for me:
#echo off
setlocal enabledelayedexpansion
dir nul
echo %ERRORLEVEL%
if .1.==.1. (
urklbkrlksdj - not a command
echo %ERRORLEVEL%
echo !ERRORLEVEL!
)
if errorlevel works without delayed expansion but works in manner similar to
if %errorlevel% <= Some_Value ... :
#echo off
::sets errorlevel to 0
(call )
if "1" == "1" (
rem sets errorlevel to 5
cmd /c exit 5
if errorlevel 4 echo this will be printed
if errorlevel 5 echo this will be printed
rem :::: you can use this ::::::::::::::
if errorlevel 5 if not errorlevel 6 echo this will be printed ONLY when the errorlevel is 5
rem :::::::::::::::::::::::::::::::::::::
if errorlevel 6 echo this will not be printed
)