Making batch files foolproof

Started by Dilbert, April 20, 2006, 12:15:54 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Dilbert

Question
I want to distribute my batch file. How can I make sure users don't mess up my batch file?

Answer
It's a fact of life that if it is possible for some knucklehead to mess it up, he/she will. There are three main methods of making sure it doesn't get botched up: 1) Explain how it works before the user uses it, 2) make a help section of the batch, and 3) add protection code to ensure that the user cannot screw up.

1. Create a readme file
Include a readme to go with your batch file, explaining the syntax, its uses and limitations. This, however, is the least reliable method, as very few people actually read it, no matter how much you tell them to read it. However, some might, and anyone that reads your readme will benefit (assuming good info is in the readme and that it's easy to understand).

2. Create a help section in your batch file

It's as easy as creating a label and liberally using the ECHO command. You could make it so that the user would trigger the help section if they made a syntax error. This section would have ideally the same info as the readme. This is more likely to be seen; however, there will still be a chance of a logic error that will slip through even the best of syntax error catchers.

3. Write code to catch errors in the usage of the batch file
Though you should include at least #2 (it is also recommended that you include #1, it's not hard), this is the most sure-fire way of making sure the user cannot damage his/her system. However, it is also the most involved of the three procedures, and usually will double or triple the file length. This should not, however, concern you. What should concern you is how to write the code in a way that is effective and serves a good purpose.

Let's take a look at an example. A user has an old version of the prompt not equipped with the move.com file that allows you to move files in DOS. This user (Average Joe) has to copy and delete the original. Mr. Joe wants his buddy to write a batch file that allows him to do what newer versions of the prompt can do. Let's say I am that buddy. The easy way out would be to write a batch file with two lines:

copy %1 %2
del %1


But this has its problems as well. What if Joe puts a directory name in, but not the filename! What happens? The file is copied to a file with the same name as the directory, and the original is erased! Well, no big deal, right? Just rename it to have a .txt or .jpg or whatever extension, right? However, this is inherently inefficient and causes grief as there is no message saying it was copied incorrectly, and it may take time for Joe to figure out he goofed.

The best way to look at writing security for a batch file is to think of all the ways it can go wrong. So, I think about the different ways the copy command can go bad:

  • The source does not exist
  • The destination directory does not exist
  • The destination file already exists

    And of course:

  • User does not specify source/destination
I. Source does not exist
Easy enough to check with the following:

IF EXIST %1 GOTO DestCheck
ECHO The file you wish to copy cannot be found. Make sure that you have
ECHO not misspelled your file name and that it does exist.


If the source file exists, it will go to a label marked DestCheck (covered next). The two ECHOs are skipped. However, if the file does not exist, the user is informed of this.

II. Destination directory does not exist
Not at all hard to do. I check the directory by attempting the copy the user wishes to make:

copy %1 %2\%1
IF ERRORLEVEL 0 GOTO DeleteSource
ECHO The directory you wish to copy to does not exist.
ECHO Please pake sure you have not misspelled the directory name.


This code block will attempt to copy the source to the directory, naming the file the same. (Note: This batch file does not support multiple file copies very well and your readme/help section should note this) If the errorlever (amount of errors) is equal to 0 (no errors), then go to the label that erases the source file; otherwise, notify the user there was an error.

III. User attempts to copy to a file that already exists
This is easy to check, and only slightly more complicated to solve. I find any pre-existing files with the block

IF EXIST %2\%1 GOTO Duplicate

and the label "Duplicate" would have the following code:

ECHO The destination file already exists. The file name
ECHO will be changed to prevent overwrite.


III. User does not specify source/destination
I simply check to see if %1 is empty with this:

IF %1=="" GOTO help
IF %2="" GOTO help


That's it! If %1 is empty, or if %2 is empty, go to the help section.
[center][/center]"The geek shall inherit the Earth."

Dilbert

#1
Putting it together
Each block does next to nothing by itself. I have to assemble it in a way that makes sense. However, to do this requires me to declare two variables: %1 and %2 need to be given variables so the values can be modified.

@ECHO OFF
IF "%1"=="" GOTO help
REM - The below I switch makes the string comparison case insensitive
IF /I "%1"=="help" GOTO help
IF "%2"=="" GOTO help

SET source=%1
SET dest=%2
SET error=

IF EXIST %source% GOTO DuplicateCheck
ECHO The source file does not exist. Please make sure the name is
ECHO spelled correctly and the file exists.
GOTO End

:DuplicateCheck
IF NOT EXIST %dest%\%source% GOTO CopyAttempt
IF "%error%"=="1" GOTO RenameLayer2
IF "%error%"=="2" GOTO Crash
ECHO The destination file already exists. The name of the destination
ECHO file will be altered to prevent overwrite. The extension of the
ECHO file will be changed; you must re-enter the correct extension yourself.
PAUSE
SET source=xxyyzzabc.one
SET error=1
cls
GOTO DuplicateCheck

:RenameLayer2
ECHO The name chosen for alteration already exists.
ECHO A new name is being chosen.
SET source=yxba.two
set error=2
GOTO DuplicateCheck

:Crash
cls
ECHO The destination folder has maxed out on the number
ECHO of renamed files it may contain. Please rename one
ECHO or both of these files with the extension ".one" or
ECHO ".two". Xmove will now close.
GOTO End

:CopyAttempt
COPY %1 %dest%\%source%
IF ERRORLEVEL 1 GOTO NoDirectory
ECHO Copy completed successfully. Deleting source...
GOTO DeleteSource

:NoDirectory
cls
ECHO The directory you chose does not exist. Please
ECHO make sure the directory you chose exists and
ECHO that you did not misspell the name.
GOTO End

:DeleteSource
DEL %1
cls
ECHO The move was completed successfully.
GOTO End

:help
ECHO MOVE.BAT syntax:
ECHO MOVE [source] [directory]
ECHO.
ECHO Note that this file does not support more than one file being copied at a time.
ECHO It will work, but the resulting name will be "wrong". Also note that if you try
ECHO to move to a file that exists, the batch will attempt to change the name of
ECHO the file. It will not allow you to copy to a directory that does not exist.
GOTO End

:End


And I was done, having a perfectly good replacement for move.com.

Phew! That's one long code for a simple concept of moving files. However, it makes sure that there is no possible way that the user can cause himself headaches (although renaming the .one and .two files takes a little work).

Another important notice
As you may know, batch files must be in a folder included in the PATH variable in order to work outside of that folder. A folder that is always in the PATH variable is System32; make sure the user knows about this, either in your readme, in the place where the file is attached/hosted, or in the help section (since it can run in the folder it's in without modifying the PATH variable).This is just one example. The general rule for other batch files is to think of every possible way the user can be a complete bonehead, then take steps to prevent it. This concept applies to all programming, from batch to C++ to FORTRAN and even Assembler.

For any out there who use a version of the prompt that doesn't have move.bat, or if you want to use this batch for fun, I have attached the batch file. If you read what I wrote in the help section, there is no need for a readme.

This post and attachment has been edited 4 times. Reasons: code error fixed; code error fixed; added cls to code; prevented infinite loop and fixed abnormal screen clearing

[old attachment deleted by admin]
[center][/center]"The geek shall inherit the Earth."