batch file test error level - error-handling

I'm trying to conditionally run an exe from a batch file conditionally upon another exe executing successfully.
I've tried a few different combinations of IF and ERRORLEVEL but none seem to work
"..\..\..\TeamBuildTypes\Current Branch\DatabaseUpdate.exe" -s localhost\sql2008r2
IF %ERRORLEVEL% 1(
"..\..\..\TeamBuildTypes\Current Branch\DatabaseUpdate.exe" -s localhost\sql2008
)
Pause
Gives me the error
1( was unexpected at this time.
Where am I going wrong here?

IF ERRORLEVEL ... is a special syntax supported since the DOS days, the %ERRORLEVEL% variable support was added in WinNT.
The original syntax is used like this:
call someapp.exe
if errorlevel 1 goto handleerror1orhigher
echo succuess...
To use the variable, use the normal IF syntax: if %errorlevel%==0 echo success...
Note that %errorlevel% stops working if someone does set errorlevel=foo and it might not get updated for internal cmd.exe commands.
An alternative solution is to use &&:
call someapp.exe && (echo success) || (echo error!)
There are (at least) two known cases where errorlevel is broken and you must use || instead:
RD/RMDir
> file redirection

Negative errorlevels can create problem. Try something like this:
IF '%ERRORLEVEL%'=='0' GOTO OK

Never use parenthesis to enclose any variables.
Parentheses are a block construct that will break DO and IF blocks and other things.
Instead use safe plain characters like "X" to enclose variables
E.g. To test for ERRORLEVEL of ONLY 0 use ...
IF X%ERRORLEVEL%X == X0X Echo or GOTO etc ...
It is safer this way as many special characters have special meanings and will break more complex code without any warning and take hours to debug. I know, this trap has befallen me whenever I forget my own advice.

Related

Declare bash variables inside sql EOF

how to declare variable in bash command. See "?"
I thought we could almost run any bash statement with ! or host in front of line
#!/bin/bash
sqlplus scott/tiger#orcl << EOF
! export v10="Hi" Doesn't work, why?
! echo $v10 Doesn't work, why?
! echo "Done" Works perfectly and also other bash commands
select * from dept; Works perfectly
exit
EOF
Thank you
What #jordanm says "probably" is exactly what is happening. When you specify a host command from within sqlplus, a separate shell process is spawned, the command executed by that process, then that process is terminated and control returns to sqlplus. Any environment variables that are set in that child shell process are good only within it, so when it terminates, they are gone.
As for your specific lines that "work" and "don't work" .. "export v10="Hi" does work but there is no stdout display of the 'export' command, and as explained, that variable v10 ceases to exist once the child process completes and control returns to sqlplus. The "echo $v10" also works, but since that is a new shell process, it has no value for $v10, so there is nothing to echo.
What are you trying to accomplish by setting enviornment variables from within sqlplus?
found it, all I had to do was
<< EOF
whenever sqlerror exit failure rollback
whenever oserror exit failure rollback
#scriptname.sql
EXIT
EOF

Batch - How to Echo %%Variable%%

I have a small problem with a batch file I'm working on.
Here's a simple sample:
I would like to get the string "THERE" as my result.
But the result I get is just "HELLO"
set hello=there
set a=h
set b=ello
set result=%a%%b%
echo %result%
I already tried something like this:
Echo %%result%%
And Sadly, it just gets me the result %HELLO%
Any help would be great. Thanks!
The reason that %%result%% gives you %result% on the output is that the %% tokens are interpreted first, and further interpretation is not done.
However, you can use that to your advantage, doing a second level of indirection with the following trick:
#echo off
set result=hello
echo %result%
call :iset second %%result%%
echo %second%
goto :eof
:iset
for /F "usebackq tokens=*" %%i in (`echo %%%2%%`) do set %1=%%i
goto :eof
The secret lies in passing the thing you want interpreted (in this case, %%result%% passes in the literal %result% as per the rules stated in the first paragraph, not the interpretation of it).
The for loop then echos the interpretation of that (hello) surrounded by %...% (again, the double %% reduces to %), so that it is also interpreted, and it uses that to set the target variable you also passed in.
The upshot is that it effectively gives you:
%(%result%)%
which is what you're after.
Might I suggest, however, that you start looking into Powershell, so that you don't have to perform these batch-gymnastics in future :-)

csh alias with variable number of arguments

I would like to create a csh alias that performs one operation if invoked without arguments and a second operation if invoked with a single argument. Does anyone know how to do this? (Attempting to refer to an argument that wasn't passed triggers an error).
I know this is a bit late but I just ran into needing something similar and hope it might still be relevant to somebody.
You can set the arguments as an array and query based on the size of the array:
alias testing 'set args_=(\!*); if ($#args_ > 0) echo "this command has $#args_ arguments" endif'
Aliases in tcsh are limited; for more advanced things, I've found that the best way is to source a (t)csh script, like so:
alias my-cmd 'source ~/.tcsh/my-cmd.tcsh'
And ~/.tcsh/my-cmd.tcsh would contain something like:
if ( $1 != '' ) then
echo "we have an argument: $1"
else
echo "we don't have an argument"
endif
Example output:
% my-cmd
we don't have an argument
% my-cmd hello
we have an argument: hello
Now, it may also be possible to do this with just an alias, but this will be much more maintainable & cleaner in the long run, IMHO.
(I've assumed tcsh here since almost all, or perhaps even all, c shells are tcsh these days).
Easy to do - sorry I'm late to the party.
alias iftest 'if (\\!:0 != \\!:$) echo "Last arg="\\!:$;if (\\!:0 == \\!:$) echo "No args given."'
This merely checks whether the 0th argument (=the 'iftest' itself) and the last arguments are the same, and if they are, assumes there is no argument. This is, of course, not necessarily true, but hopefully works in praxis.

Batch IF statement variable inside another variable

I'm having a problem with a framework for a batch game I'm trying to create. I want to check if a variable is something other than a blank space. However, which variable I'm trying to check is in itself defined by two variables. For example:
if not %px%xplayerlocation%y%yplayerlocation%%==%blank% goto wherever
As you can see, the variable to be checked is determined by the values of %xplayerlocation% and %yplayerlocation%. To my knowledge, only the outermost %% signs are being read as being a variable and the inner ones are being read as literal percent signs. Does anyone know a way around this problem? I'll give any additional information if anyone needs it. Thanks.
#ECHO OFF
SETLOCAL
SET "blank= "
SET xplayerlocation=3
SET yplayerlocation=4
ECHO test with blank================
SET px3y4=%blank%
CALL SET varval=%%px%xplayerlocation%y%yplayerlocation%%%
if not "%varval%"=="%blank%" ECHO goto wherever - NOT blank
ECHO test with "Q"================
SET px3y4=Q
CALL SET varval=%%px%xplayerlocation%y%yplayerlocation%%%
if not "%varval%"=="%blank%" ECHO goto wherever - NOT blank
GOTO :EOF
This should get you out of trouble.
You have recognized the source of the problem, but your description of the behavior is incorrect. The parser will attempt to expand variables named px and y, and it will convert the final %% into %.
The Magoo solution will work, but using CALL is quite slow. That may not be a problem for many small scripts, but for a batch game it can kill performance.
You want delayed expansion. Include setlocal enableDelayedExpansion near the beginning of your script. Then use the following:
if not !px%xplayerlocation%y%yplayerlocation%!==%blank% goto wherever
Normal %var% expansion occurs early at parse time, and !var! expansion occurs late at execution time, so you get the proper result.
The above will not work if the value of %blank% is a space. The simplest solution would be to use delayed expansion for !blank! as well.
You might find yourself in a situation where the coordinate values need to be set and expanded within the same block of code, like in a FOR loop or IF statement:
setlocal enableDelayedExpansion
...
REM This does not work
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
if not !px%xplayerlocation%y%yplayerlocation%!==!blank! REM doSomething
...
)
The above will not work because %var% expansion occurs at parse time, and the entire parenthesized block of code is parsed before any code is executed. So the expanded value is constant - it will expand to the value that existed before the loop started.
The solution is to transfer the coordinate values to FOR variables using delayed expansion:
setlocal enableDelayedExpansion
...
REM This works
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
for %%X in (!xPlayerLocation!) do for %%Y in (!yPlayerLocation!) do (
if not !px%%X%y%%Y!==%blank% REM doSomething
)
...
)
or
setlocal enableDelayedExpansion
...
REM This also works
for ... in (...) do (
...
set /a "xPlayerLocation+=xChange, yPlayerLocation+=yChange"
for /f "tokens=1,2" %%X in ("!xPlayerLocation! !yPlayerLocation!") do (
if not !px%%X%y%%Y!==%blank% REM doSomething
)
...
)
If you are serious about developing a high quality game using batch, then you may be interested in studying the techniques I used in developing SNAKE.BAT - an arcade style game using only native batch commands. The beginning of the post is a bunch of code, but afterwards I describe a number of techniques I used for improving performance. It is advanced stuff, so don't try to absorb everything at once. Absorb what you can, and then revisit the post later on after you gain more experience.

How do I request and receive user input in a .bat and use it to run a certain program?

This is what I have so far
#echo off
:Ask
echo Would you like to use developer mode?(Y/N)
set INPUT=
set /P INPUT=Type input: %=%
If %INPUT%=="y" goto yes
If %INPUT%=="n" goto no
If %INPUT%=="Y" goto yes
If %INPUT%=="N" goto no
:yes
java -jar lib/RSBot-4030.jar -dev
echo Starting RSbot in developer mode
:no
java -jar lib/RSBot-4030.jar
echo Starting RSbot in regular mode
pause
Either way if the user enters y or n it always runs in -dev mode.
How do I make it run in -dev mode if the answer is yes, and regular mode if the answer is no. Also, how do I make it ask again if the input isn't Y, N, y, or n?
If the input is, say, N, your IF lines evaluate like this:
If N=="y" goto yes
If N=="n" goto no
…
That is, you are comparing N with "y", then "n" etc. including "N". You are never going to get a match unless the user somehow decides to input "N" or "y" (i.e. either of the four characters, but enclosed in double quotes).
So you need either to remove " from around y, n, Y and N or put them around %INPUT% in your conditional statements. I would recommend the latter, because that way you would be escaping at least some of the characters that have special meaning in batch scripts (if the user managed to type them in). So, this is what you should get:
If "%INPUT%"=="y" goto yes
If "%INPUT%"=="n" goto no
If "%INPUT%"=="Y" goto yes
If "%INPUT%"=="N" goto no
By the way, you could reduce the number of conditions by applying the /I switch to the IF statement, like this:
If /I "%INPUT%"=="y" goto yes
If /I "%INPUT%"=="n" goto no
The /I switch makes the comparisons case-insensitive, and so you don't need separate checks for different-case strings.
One other issue is that, after the development mode command is executed, there's no jumping over the other command, and so, if the user agrees to run Java in the development mode, he'll get it run both in the development mode and the non-development mode. So maybe you need to add something like this to your script:
...
:yes
java -jar lib/RSBot-4030.jar -dev
echo Starting RSbot in developer mode
goto cont
:no
java -jar lib/RSBot-4030.jar
echo Starting RSbot in regular mode
:cont
pause
Finally, to address the issue of processing incorrect input, you could simply add another (unconditional) goto command just after the conditional statements, just before the yes label, namely goto Ask, to return to the beginning of your script where the prompt is displayed and the input is requested, or you could also add another ECHO command before the jump, explaining that the input was incorrect, something like this:
#echo off
:Ask
echo Would you like to use developer mode?(Y/N)
set INPUT=
set /P INPUT=Type input: %=%
If /I "%INPUT%"=="y" goto yes
If /I "%INPUT%"=="n" goto no
echo Incorrect input & goto Ask
:yes
...
Note: Some of the issues mentioned here have also been addressed by #xmjx in their answer, which I fully acknowledge.
i just do :
set /p input= yes or no
if %input%==yes echo you clicked yes
if %input%==no echo you clicked no
pause
Here is a working example:
#echo off
:ask
#echo echo Would you like to use developer mode?(Y/N)
set INPUT=
set /P INPUT=Type input: %=%
If /I "%INPUT%"=="y" goto yes
If /I "%INPUT%"=="n" goto no
goto ask
:yes
#echo you select yes
goto exit
:no
#echo you select no
goto exit
:exit
#pause
I have improved batch file with yes or no prompt. If user enter any character except y and n , then it will again prompt user for valid input. It Works for me.
#echo off
:ConfirmBox
set /P c= Are you sure want to contine (y/n)?
if /I "%c%" EQU "Y" (
goto :FnYes
) else if /I "%c%" EQU "N" (
goto :FnNo
) else (
goto :InValid
)
:FnYes
echo You have entered Y
goto :END
:FnNo
echo You have entered N
goto :END
:InValid
echo Invalid selection. Enter Y or N
goto :ConfirmBox
:END
pause
exit
/I in if condition will validate both lowercase and uppercase characters.
echo off
setlocal
SET AREYOUSURE = N
:PROMPT
set /P AREYOUSURE=Update Release Files (Y/N)?
if /I %AREYOUSURE% NEQ Y GOTO END
set /P AREYOUSURE=Are You Sure you want to Update Release Files (Y/N)?
if /I %AREYOUSURE% NEQ Y GOTO END
echo Copying New Files
:END
This is code I use regularly. I have noticed in the examples in this blog that quotes are used. If the test line is changed to use quotes the test is invalid.
if /I %AREYOUSURE% NEQ "Y" GOTO END
I have tested on XP, Vista, Win7 and Win8. All fail when quotes are used.
I don't know the platform you're doing this on but I assume Windows due to the .bat extension.
Also I don't have a way to check this but this seems like the batch processor skips the If lines due to some errors and then executes the one with -dev.
You could try this by chaning the two jump targets (:yes and :no) along with the code. If then the line without -dev is executed you know your If lines are erroneous.
If so, please check if == is really the right way to do a comparison in .bat files.
Also, judging from the way bash does this stuff, %foo=="y" might evaluate to true only if %foo includes the quotes. So maybe "%foo"=="y" is the way to go.
Depending on the version of Windows you might find the use of the "Choice" option to be helpful. It is not supported in most if not all x64 versions as far as I can tell.
A handy substitution called Choice.vbs along with examples of use can be found on SourceForge under the name Choice.zip
Add quotation marks (" ") around the %INPUT% so it looks like this:
If "%INPUT%" == "y" goto yes
If "%INPUT%" == "n" goto no
If "%INPUT%" == "Y" goto yes
If "%INPUT%" == "N" goto no
try this for comparision
if "%INPUT%"=="y"...