External Commands

These are the executable utilities included with the MSDOS package. They are free standing programs in their own right, but some of them are useful in batch files because they do something interesting or because they can be used to extract information from the system or user. Most of the .COM and .EXE files in your \DOS directory fit the general description, but only a few have proven to be useful for information gathering. Interestingly enough, COMMAND.COM falls in the useful for doing things and useful for getting information categories.


CHOICE
is an executable that returns key information as ERRORLEVEL. It is discussed in the DOS 6 HELP program, and will not be addresseed here. Rather, I'll show a somewhat slicker approach using a pair of tiny executables I worte some years ago that behave very differently from CHOICE. The "Batch and DEBUG" section contains batch files to create both programs. KPAUSE and KPAUSED don't actually pause to read keys - they read them on the fly, so you can press a hot key anywhere during the batch file before they run to have them act on the key. The former does not consume the key, so that it can be tested with another program later, or even passed through to the DOS prompt at the end of the batch file. This allows typing the next command and having the batch file act on its knowledge of what is to happen after it terminates. KPAUSED does consume a single key press. I use these in AUTOEXEC.BAT to provide invisible means for aborting various parts of the initialization code: <Space> aborts complety, immediately after setting up the path and prompt, while any key prevents launching Windows. Since the Windows abort key may or may not have been pressed by the first test, the first test does not consume the key, unless it is <Space>. The code shown here is drastically purely for demonstration - it includes two DIR commands to generate delays and indicate the paths through the code (in AUTOEXEC.BAT, the key can be pressed any time after the BIOS has activated the key buffer, as during CONFIG.SYS).


 @echo off
 dir c:\dos 
 kpause
 if errorlevel 32 if not errorlevel 33 goto done
 dir c:\dos
 :done
 kpaused
 if errorlevel 1 goto end
 win
 :end
IF ERRORLEVEL n IF NOT ERRORLEVEL n+1 isolates a specific value of ERRORLEVEL - the test is basically an equals or is qreater than test.

COMMAND /e:nnn /cFOO
is useful both in batch files and from the command line to spawn a secondary (or tertiary, or later) command processor with a specified environnment size (in bytes specified by nnn in the /e:nnn switch), and have it execute the program specified in the /c switch. It was several effects and side effects, notably that it does get a new environment, distinct from the parent environemnt, and that the output of the command processor can be redirected to a file or device, which, if the program is a batch file that has not turned echoing off, will redirect the command display from the batch file (see: Debugging Batch Files).

UNDELETE
Now here's an oddity - unlike the other DOS utilities, UNDELETE writes its error messages to STDOUT instead of STDERR. This means that we can pipe the *errors* through FIND and take action based on them. The user need not deal with the error messages or even see them. One of the most useful UNDELETE syntaxes is the one with the /list switch: UNDELETE d:\*.* /list. With this you can tell if a drive or directory exists, - even on a Novell LAN drive (if exist d:\foo\nul fails there and other places). You can even find out if the drive is a physical or logical drive and whether it is SUBSTed or is something else (CDs and LAN drive look alike)

These tricks tend to fail in WIN95, NT, and OS/2, but those OSs are outside the scope of this book.


This code determines whether a directory exists on the given drive. It is unusual in that it doesn't fail with CDs, Novell (and other) LAN drives, or even empty floppy drives. It does fail under WIN95, NT, and OS/2 (or so I'm told), but those are outside the scope of this work. The second example is more extensive than would normally be needed because it also extracts whatever information it can about the nature of the drive. Both the directory checker and the drive type identifiers use mostly well known and understood techniques - notably the technique of redirecting the output of FIND to a file and attempting to copy the file in order to tell if it contains something or nothing (COPY will not copy an empty file).

 @echo off
 echo a| undelete %1\*.* /list | find /i " %1" > %temp%\}1{.dat
 copy %temp%\}1{.dat %temp%\}2{.dat > nul
 del %temp%\}1{.dat
 if not exist %temp%\}2{.dat goto no
 echo Path exists
 del %temp%\}2{.dat
 goto end
 :no
 echo Path not found.
 :end

The key to the function of that example is the fact (mentioned above) that UNDELETE does not observe the MS convention that error messages should not be redirectable (and the user should therefore not be able to do uninteresting things like create error log files) - this is understandable since the program wasn't written by Microsoft (it comes from Central Point Software. The information of interest may in fact in the error messages (as below). This example forces its transient files to be created in the directory given in the TEMP environment variable - if this is not set at all they go into the root of the default drive (not the best of places). The copy command is redirected to NUL to surpress display of the "One file copied" message

The, perhaps perplexing, "ECHO a" piped to UNDELETE is there in case of removable media that are in fact removed (empty floppy or CD drive) - it responds to the ARF prompt with an "A" for "abort".

One interesting point that is not exactly a batch language issue is left for the reader: What happens if the drive is a CD containing an audio disk?


This related code tells what can be determined about the drive from UNDELETE.

 @echo off
 set type=Does not exist
 echo a| undelete %1\*.* /list > %temp%\}1{.dat
 find /i " network" < %temp%\}1{.dat > %temp%\}2{.dat
 copy %temp%\}2{.dat %temp%\}x{.dat > nul
 del %temp%\}2{.dat
 if not exist %temp%\}x{.dat goto notnet
 set type=Network or CD (non-FAT drive)
 del %temp%\}x{.dat
 goto done
 :notnet
 find /i " subst " < %temp%\}1{.dat > %temp%\}2{.dat
 copy %temp%\}2{.dat %temp%\}x{.dat > nul
 del %temp%\}2{.dat
 if not exist %temp%\}x{.dat goto notsubst
 set type=SUBSTed drive
 del %temp%\}x{.dat
 goto done
 :notsubst
 find /i " abort " < %temp%\}1{.dat > %temp%\}2{.dat
 copy %temp%\}2{.dat %temp%\}x{.dat > nul
 del %temp%\}2{.dat
 if not exist %temp%\}x{.dat goto notempty
 set type=Empty removable media drive or drive error
 del %temp%\}x{.dat
 goto done
 :notempty
 find /i "invalid" < %temp%\}1{.dat > %temp%\}2{.dat
 copy %temp%\}2{.dat %temp%\}x{.dat > nul
 del %temp%\}2{.dat
 if not exist %temp%\}x{.dat goto noterr
 set type=Drive not found or unreadable drive
 del %temp%\}x{.dat
 goto done
 :noterr
 set type=Local hard or floppy drive
 :done
 del %temp%\}1{.dat
 echo %type%
 :end

Some other information can be extracted, but I do need to leave something for the reader to tackle on his/her own. For example, if the drive is local and FIND reports that A: or B: was found in the file, it's usually safe to assume that the drive is a floppy (but not the other way around - I frequently encounter machines with floppies for C: and/or D:). The reader is invited to explore and experiment - as long as you make sure to use the /list switch, UNDELETE is pretty harmless.


LOADFIX

The intent of LOADFIX is to eat up the first 64K of memory so that certain programs that missuse segment wraparound or otherwise can't run if loaded in the first 64K of memory can be run. The program just eats the memory and executes whatever program it was passed as its first argument and passes that the rest of the command line. It would appear that LOADFIX would be of little interest to batch programmers, but that is far from the case: it provides the core of a solution to the long standing problem of executing a command on a list of items (e.g., a list of directories or files) because the program to execute can be a batch file.

My plan was to explore the list processing idea here, but it grew too large and has been moved to its own "List Processing" page.


  ** Copyright 1995, 1996, Ted Davis - all rights reserved ** 

Input and feedback from readers are welcome. NOTE: the subject of the message must contain the word "batch" for the message to get past the spam filter.

Back to the Table of Contents page

Back to my personal links page - back to my home page