I tried to write an batch file using ERRORLEVEL.
Unfortunatly it´s not working (or better not working the way I expect).
It seems to be that ERRORLEVEL is not available as an environment variable.
on cmd:
if %errorlevel% == 0 echo test
result:
no echo
on cmd:
if %errorlevel% == %errorlevel% echo test
result:
test
on cmd:
echo %errorlevel%
result:
%errorlevel%
Read about using setlocal, but setlocal cannot be executed
Any ideas?
Thank you in advance!
ERRORLEVEL requires a process or function to be carried out in order to display an input. Say for instance you wanted to Ping Google and if successful it would print out "Good" or if it failed printed out "Bad", that's where ERRORLEVEL would come into effect. You cannot use ERRORLEVEL if a process or function is not present.
EX.
echo off
goto :pingtest
cls
:pingtest
cls
ping www.google.com
if errorlevel 2 goto :good
if errorlevel 1 echo :bad
:good
cls
echo Good
echo[
pause
:bad
cls
echo Bad
echo[
pause
As you can see from the code above, there was a process involved.
Also if you get the chance could you check out my blog? http://pryrotech.weebly.com
Related
I'm trying to force the user to run the script using administrative privileges:
#echo off
net session >nul 2>&1
if %errorlevel% == 0 (
echo Success: Administrative permissions confirmed.
echo.
echo Please Choose:
echo 1. Enable
echo 2. Disable
echo 3. Exit
set /p choice="> "
echo Choice: "%choice%"
) else (
echo Failure: Please run as administrator
)
pause
The net session and errorlevel lines check the privilege, and this works. The weird thing is that no matter what gets entered for choice it behaves as if it was never initialized.
The code running inside the if block works fine by itself, so I suspect the issue has something to do with how I'm checking for privileges.
Can someone explain this behavior, and any fixes?
You'd need either delayed expansion or avoid it by reorganizing your code a bit, like:
#echo off
net session >nul 2>&1
if %errorlevel% == 1 (
echo Failure: Please run as administrator
exit 1
)
echo Success: Administrative permissions confirmed.
etc.
The issue is because you are setting a variable within an If block, without delaying variable expansion.
However, you don't need the if block at all, nor do you need to set a variable for the selection.
The following method uses the || which essentially means 'if previous command produced an error', replaces the Set /P command with Choice and uses timed pauses via the Timeout command:
#Echo Off
Net Session >Nul 2>&1 || (
Echo Failure: Please run as administrator
Timeout 3 /NoBreak >Nul
Exit /B
)
Echo Success: Administrative permissions confirmed.
Echo=
Echo 1. Enable
Echo 2. Disable
Echo 3. Exit
Choice /C 123 /M "Please Choose"
If ErrorLevel 3 Exit /B
If ErrorLevel 2 GoTo Disable
Echo Enabling
Timeout 3 /NoBreak >Nul
Exit /B
:Disable
Echo Disabling
Timeout 3 /NoBreak >Nul
Exit /B
The following Windows batch file called "foo.bat" echos "quitting" and sets the return code to 1 as I expect:
if "1"=="1" (
if "1"=="1" (
echo quitting
exit /B 1
)
)
But, to my surprise, the return code of this batch file is 0:
if "1"=="1" (
if "1"=="1" (
echo quitting
exit /B 1
)
echo anything
)
I determine the batch file's return code like so in the Windows command prompt:
> cmd.exe /c foo.bat
quitting
> echo %ERRORLEVEL%
0
I've verified that ERRORLEVEL is not already set in my environment, running set ERRORLEVEL prints "Environment variable ERRORLEVEL not defined" as expected.
Everything else about the second file works as expected. It does echo "quitting" and does not echo "anything". It appears that adding the echo anything line to the script means that the line exit /B 1 still exits but does not set the return code.
This is Windows 7 in EC2. ver reports "Microsoft Windows [Version 6.1.7601]".
Is there a way to ensure exit /B 1 really sets the return code, even in complex if statements?
If I change the file extension from ".bat" to ".cmd", then it behaves as expected.
What is your test environment?
Are you shure therE are no other side effects involved?
This batch got the expected results in Win7Ult and Win10pro
#Echo off&SetLocal EnableExtensions EnableDelayedExpansion
ver > nul
Call :First
Echo called First ErrorLevel = %Errorlevel%
ver > nul
Call :Second
Echo called Second ErrorLevel = %Errorlevel%
Pause
Goto:Eof
:First
if "1"=="1" (
if "1"=="1" (
echo quitting
exit /B 1
)
)
Goto :EoF
:Second
if "1"=="1" (
if "1"=="1" (
echo quitting
exit /B 1
)
echo anything
)
quitting
called First ErrorLevel = 1
quitting
called Second ErrorLevel = 1
I had the same trouble. I solved it with something like this:
if "1"=="1" (
if "1"=="1" (
echo quitting
goto Exit1
)
echo anything
)
goto :Eof
:Exit1
exit /b 1
Another "known" defect is this:
rem t.bat
copy non-existing somewhere
rem
C:\> cmd /c t.bat
The system cannot find the file specified.
C:\> echo %errorlevel%
0
Explicit returning of errorlevel at end of batch file does not work when run with cmd /c if there is a comment after (or echo or something that is supposed to not normally change the errorlevel). So need to use this instead:
rem t.bat
copy non-existing somewhere
exit /b %errorlevel%
rem
C:\> cmd /c t.bat
The system cannot find the file specified.
C:\> echo %errorlevel%
1
I've been using batch for a while now and I just recently ran into a problem I never encountered before involving ERRORLEVELS.
Here is a short program I made to show off the error.
#echo off
title Choices
CMD /C EXIT 0
echo [1] Choice 1
echo [2] Choice 2
echo [3] Choice 3
choice /c 123 /n
IF ERRORLEVEL 1 GOTO ONE
IF ERRORLEVEL 2 GOTO TWO
IF ERRORLEVEL 3 GOTO THREE
echo Nice you broke it
pause
exit
:ONE
echo CONGRATS YOU CHOSE 1
pause
exit
:TWO
echo NICE YOU CHOSE 2
pause
exit
:THREE
echo OOH YOU CHOSE 3
pause
exit
Its very simple and all you do is press a number and it says what number you pressed. The problem is no matter what i press it always outputs what would happen when I press 1. I used to use %errorlevel% and that worked fine but then it stopped working so I switched to the new method (IF ERRORLEVEL WHATEVER) and now it wont work either.
Please read the Microsoft support article Testing for a Specific Error Level in Batch Files.
And open a command prompt window, run if /? and read the output help, especially the paragraph about errorlevel.
The solution for your batch file is very simple, reverse the order of the lines testing on errorlevel:
#echo off
title Choices
CMD /C EXIT 0
echo [1] Choice 1
echo [2] Choice 2
echo [3] Choice 3
choice /c 123 /n
IF ERRORLEVEL 3 GOTO THREE
IF ERRORLEVEL 2 GOTO TWO
IF ERRORLEVEL 1 GOTO ONE
echo Nice you broke it
pause
exit
:ONE
echo CONGRATS YOU CHOSE 1
pause
exit
:TWO
echo NICE YOU CHOSE 2
pause
exit
:THREE
echo OOH YOU CHOSE 3
pause
exit
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 would like to make a little file. Here is a small part of the code...
#echo off
:hi
set /p "input=>>"
%input%
pause
Ok! But now i'd like to add something like this...
IF %input% error with execution goto error
IF %input% execution successful goto great
Of course I improvised a bit. Any command(s) I could use?
there is also a variable named %ERRORLEVEL% which is very useful:
#echo off
:hi
set /p "input=>> "
%input%
if %errorlevel%==9009 echo not a valid command & goto :hi
if %errorlevel%==0 echo successful & goto :hi
echo failed with errorlevel %errorlevel%
goto :hi
Note : %errorlevel% 9009 means "no such command"; %errorlevel% 0 means "command was successful", any other %errrorlevel% means "error".