In-Depth Error Handling

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
orange_batch
Expert
Posts: 442
Joined: 01 Aug 2010 17:13
Location: Canadian Pacific
Contact:

In-Depth Error Handling

#1 Post by orange_batch » 13 Aug 2010 08:14

I would like to know more about batch error handling, if there's anything I don't know.

Edit: I'm dealing only with tools installed with the OS from Windows XP, so no "choice" or anything, just basic DOS batch.

Are there any caveats to using logical OR || after a command for generic error handling?

I haven't seen it, but are there any commands that issue different errorlevels based on the type of failure they encounter? If not, why use errorlevels at all when you can use logical OR? Edit: Err, though errorlevels are obviously useful where logical OR can't be used (for loops, etc) or when doing more complex error handling, but my question still remains...

Perhaps most importantly, what about handling special characters in path/file names, strings/variables, or user input where an escape character can't be used, or even causes problems?

I think that most problems would arise when requiring user input and they use special characters like < > | " (and to a lesser extent, ! and ^) which make cmd crash anywhere later. The only workaround I know is to try and predict these failures which make the script/cmd crash by separating the susceptible code and loading it in an internal child instance of cmd, and then error handling that instance as it crashes back to the main script. (Of course, if you need to pass a variable, it has to be done through redirection to a file or the registry.)

Here's my example workaround for the handling in this case:

Main script:

Code: Select all

:retry
cmd /c user_input.bat 2>nul || (echo Failed. No special characters allowed.
goto retry)


user_input.bat would just be anything that has "set /p" and does something to the input - where the failure occurs encountering a special character.

So, am I at the peak of batch error handling or is there more?

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: In-Depth Error Handling

#2 Post by aGerman » 14 Aug 2010 09:55

orange_batch wrote:Are there any caveats to using logical OR || after a command for generic error handling?

If a command returns errorlevels at all and which errorlevels it returns depends on the command you used.
Generally if a command returns an errorlevel greater than 0 you can use || to handle it.


orange_batch wrote:I haven't seen it, but are there any commands that issue different errorlevels based on the type of failure they encounter? If not, why use errorlevels at all when you can use logical OR?

You have to use IF statements to handle different errorlevels.
Example: FIND
0 Target string found
1 Target string missing
1 find /?
2 Parameter format not correct
2 Specified file to search not found
2 Specified file in use + Fail reply
2 Drive not ready + Fail reply
5 Specified file in use + Abort reply
5 Drive not ready + Abort reply
Search the internet for other commands.

Two possible ways for IF statements:
-1)
if errorlevel 5 ...
means that the value is 5 or greater than 5. So you have to compare the values step by step in descending order.

-2)
You can use the %errorlevel% variable
if %errorlevel%==5 ...
means that the value must be exactly 5.

orange_batch wrote:Perhaps most importantly, what about handling special characters in path/file names, strings/variables, or user input where an escape character can't be used, or even causes problems?

I think that most problems would arise when requiring user input and they use special characters like < > | " (and to a lesser extent, ! and ^) which make cmd crash anywhere later.

You can't use <>| in pathes or file names, but you could escape it. Also ^ and &.

Code: Select all

@echo off &setlocal
set /p "var=Enter something: "
if not defined var goto out
set "var=%var:^=^^%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:|=^|%"
set "var=%var:&=^&%"
:out
echo\%var%
pause


Regards
aGerman

orange_batch
Expert
Posts: 442
Joined: 01 Aug 2010 17:13
Location: Canadian Pacific
Contact:

Re: In-Depth Error Handling

#3 Post by orange_batch » 14 Aug 2010 21:53

Thanks aGerman, I thought you would reply.

I just spent a few hours doing tests with special characters. I would blame myself for not realizing this, but I found out why you put quotes around the text following set. I've never seen written ANYWHERE in DOS tutorials that this is how you read special characters like normal characters, only that it's a good way to make sure there are no trailing spaces in your variable (useless). This changes a lot! I'm a little peeved! It says so quietly and not very accurately on the Microsoft website though...

I'm going to keep doing some tests to figure out a few things, like an escape function, string manipulation, command line effects and handling string quotes.

Edit: Hmm okay, is there any way to handle string quotes when they are surrounded in special characters?

Example,

Code: Select all

set "myvar=|"^|"    // or set myvar=^|"|
:: myvar=|^|
set "catch=%myvar:"=^"%"   fails (| is processed)
set catch=%myvar:"=^"%     fails (| is processed)
set "catch=%myvar:|=^|%"   makes catch=^|"| (would fail if it contained any other special character as well)
set catch=%myvar:|=^|%     makes catch=|"^| (would fail if it contained any other special character as well)


This time I believe it's another limitation of DOS, it simply won't work.

Edit: Here's that escape function I mentioned. This is based on your example aGerman. I tried a bunch of things and I think it's also the only way to do this. Doing this in a for loop fails due to variable expansion conflicts. A subroutine might be possible, but wouldn't be much different/smaller, so it's redundant. It can be modified if desired.

Code: Select all

@echo off&setlocal enabledelayedexpansion

set /p "yourvar= Enter something: "
call :escape yourvar
set yourvar
echo yourvar unescaped: %yourvar%
pause
exit/b

:escape
if not defined %1 exit/b
set "%1=!%1:^=^^!"
set "%1=!%1:<=^<!"
set "%1=!%1:>=^>!"
set "%1=!%1:|=^|!"
set "%1=!%1:&=^&!"
exit/b


I tried to include a processor for exclamation marks, since they're lost during expansion too, but it doesn't work properly alongside the loss of carets...

At least, the only user interaction I need requires a single character for input, so if I just cut their input variable down to the first character I can avoid the problem with quotes surrounded by special characters. Then I should also not need that child cmd instance workaround... :) For the sake of the knowledge of DOS behaviour I'm going to keep looking out for things like this though.

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: In-Depth Error Handling

#4 Post by aGerman » 15 Aug 2010 07:16

Hehe batch and special characters -- a neverending story :wink:

Here I had similar problems. And yes, EnableDelayedExpansion can solve more problems than you probably think.
If you use it you don't need to escape.

Code: Select all

@echo off&setlocal enabledelayedexpansion

set /p "yourvar= Enter something: "
echo yourvar unescaped: !yourvar!
pause


Provided that you use !! instead of %%.

Regards
aGerman

Post Reply