Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Windows NT tricks, traps and undocumented features

161 views
Skip to first unread message

Walter Zackery

unread,
Sep 21, 1999, 3:00:00 AM9/21/99
to
Although the Windows NT command-line interface is far, far superior to
Microsoft's other command-line offerings, it also has its share of
bugs, quirks and undocumented stuff. This is some of the stuff that
I've encountered while working with NT. I'll be glad to hear any
corrections, additions, amplifications or workarounds. This is far
from being an exhaustive list, so I may update it periodically.


The FOR command with the /R switch has a peculiarity. If a directory
other than the current directory is to be processed, then that
directory must be passed to FOR /R as an unquoted short filename.
Quoted short filenames and virtually all long filenames, quoted or
unquoted, passed to FOR will cause the batch file to fail.


REG.EXE has a bug involving the key hkey_classes_root. The REG QUERY
command will not expand any key in HKCR that has a non-empty default
value. The only apparent workaround is to use HKLM\software\classes
instead of HKCR in REG QUERY expressions.


The help file on the MD command fails to mention that you can create
multiple directories at once by specifying the name and path of the
directories as multiple command-line parameters. If no path is
specified, then the directories are created in the current directory.


The help file on the RD command fails to mention that you can remove
multiple directories at once by specifying them as command-line
parameters. If the /s switch is used, the directories will be deleted
even if they contain content.


The NT help file mentions that the label :EOF is always implied in NT
batch files as the end-of-file label, which means that you can always
use GOTO:EOF to terminate a batch file or goto the end of the file.
This is a very useful feature. What the help file fails to mention is
that there are a couple of bugs associated with the GOTO:EOF command.
Bug #1 is that you MUST use the colon when you use this command; GOTO
EOF will not work. An even more insidious bug is that there cannot be
a trailing space after GOTO:EOF! If there is one, NT complains that it
can't find the label called :EOF! The best workaround is to ALWAYS
wrap this command in parentheses when you use it. In other words,
always use (GOTO:EOF) instead of GOTO:EOF.


I'm still researching this one, but the SETLOCAL command appears to
have many undocumented effects when it's used in a batch file. If it's
issued without an accompanying ENDLOCAL command, then when the batch
file terminates, the SETLOCAL command will reset the current directory
to what it was at the time the command was issued; it doesn't matter
how many CD and PUSHD commands you may have issued since then. It even
overrides a POPD command for a PUSHed stack. An interesting sidebit
here is that if no SETLOCAL command is in effect, then POPD will work
with the CD command in much the same way that it works with the PUSHD
command.


As all NT batch file writers undoubtly know, NT provides no debugging
tools for batch files. The most widely used current procedure is to
turn ECHOing ON and to insert strategic PAUSE and ECHO commands in the
script to try to determine what's going wrong. One bothersome fact
that may not be widely known is that if your script CALLs another
batch file then you need to turn ECHOing ON for that batch file also;
else not only only will it run with ECHOing OFF when it's CALLed, it
will probably turn ECHOing OFF for the rest of the procedure in the
main script!


It's fairly well-known that the parameter %* represents all parameters
that were passed to the batch file when it was launched. What may not
be so well-known is that %* can also represent all parameters that are
passed to a label by the CALL command. What's even more interesting is
that %* retains all delimiters that separate parameters as well.
Astute batch filers can use this fact to retain delimiters when
processing command lines.


To ensure that no inadvertant trailing spaces are in an environmental
variable, always issue SET commands wrapped in parentheses. The same
thing applies when you're ECHOing data to a file. It's good practice
to wrap the ECHO command in parentheses to ensure that no traling
spaces are ECHOed. This is especially important when the outcome of
your batch file hinges on testing file sizes of redirected data.

The bare numbers 0,1 and 2 normally can't be redirected to a file
using the ECHO command. To redirect these numbers, one approach is to
use the carat ^ in front of the numbers to escape them. It's a good
idea to use the carat to escape any environmental variable that could
possibly have one of those values.

Another way of accomplishing the same thing above that's more useful
is to use one of the following characters after the ECHO command:

. / \ [ ] + (

In other words, ECHO[1>file or ECHO.2>file or ECHO\0>file,etc. will
all work to echo or redirect those troublesome characters.

The reason that the above approach is more useful than the carat is
that it also serves nicely to redirect or echo three other troublesome
characters: = , ; the DOS delimiters. If you type ECHO = at the
command prompt, NT will respond that ECHOing is on (or off) rather
than ECHOing an equal sign to the screen. In a thread concerning this
subject a few weeks ago, I suggested an elaborate 3-line procedure to
get around this problem in a script. The best suggestion at the time
was to use COMMAND /CECHO = to ECHO an equal sign. The problem that I
have with this approach is the invocation of COMMAND.COM. There's at
least one ill effect that I know of when COMMAND.COM is invoked in a
script or at the command line: the current directory and all future
directories are instantly changed to their short filename form at the
prompt (they aren't renamed to short name). This is definitely
undesireable if you must parse for the long filename components of the
current directory. This can be avoided by using the following syntax
to echo or redirect delimiters:

ECHO[= or ECHO.= or ECHO\; or ECHO/, or ECHO+= etc.

If you have an NTFS partition, you can compress any file in that
partition on-the-fly by placing a BAT or CMD file in the SendTo folder
with the following command line:

@COMPACT /C %1

By the same token, you can decompress any file compressed by NT itself
with the following command line:

@COMPACT /U %1


There appears to be a bug in the DIR command's implementation of some
(but not all) of the switch overriders; some of them not only don't
work, they have the opposite intended effect. For example, if you
type:

DIR/-P %systemroot%\system32

at the command prompt, you would expect for the screen output to
scroll without pausing, because the /-P switch should override a /P
switch that may be set in the DIRCMD environmental variable. What
actually happens is that the screen output is paused after each
screenful! This happens whether or not the DIRCMD variable is set to
/P or not. The same effect happens when you use the /-B switch. NT
ignores the - part of the switch and shows bare format filenames. So
always carefully test the switch overriders to make sure that they
actually do what they're supposed to do. In the meantime, the
workaround that I've found for this bug is to list the switch twice.
For example, the following command line will override a /P switch set
by the DIRCMD variable:

DIR/-P/-P %systemroot%\system32

Don't bother asking me why the above syntax works.


Here's a trick for enabling any file or folder to "open" the Sendto
folder or any subdirectory of the Sendto folder. Stick a BAT or CMD
file inside the Sendto folder that contains the following command
line:

@start/max explorer /e,%0\..

Now if you right-click any file or folder in NT and "send" it to the
BAT or CMD file that contains this command line, the Sendto folder
will be opened. If the BAT or CMD file is located in a Sendto
subdirectory, then the same trick will open that subdirectory. Note
that no action whatsoever is taken on the right-clicked file or folder
itself. Note that in order for this to work, the default action for
BAT and/or CMD files (whichever extension you used) has to be to run
when double-clicked. If the default action is to open in Notepad or
another text editor, that's what will happen when you "send" a file or
folder to the batch file; the batch file will merely be opened in
Notepad instead of opening the Sendto folder.


If you find yourself filtering text files or NT command output a lot
with the MORE command while at the command line, then you should
consider setting the %MORE% environmental variable in the Control
Panel. The setting that I like for this variable is something like
this:

more=/e/c/s

The /e switch enables the use of extended features for the MORE
command, the /c switch forces NT to clear the screen before it begins
filtering through MORE, and the /s switch squeezes multiple blank
lines into a single line. Note that you must use the /e switch in
order to be able to use any other switch. Type MORE/? at a command
prompt for detailed help on the various switches available for this
command.


Unlike the MOVE commands of Dos 6.x and Windows 9x, the WinNT MOVE
command will not allow you to overwrite an existing file of the same
name in the destination. Surprisingly this command has no command
extensions associated with it even though it's an internal command
(also unlike Dos and Win9x). None of the MOVE commands allow you to
move a directory from one drive to another. Microsoft probably
considers this as a protective feature to dissuade you from easily
relocating vital system directories; I consider this a design flaw.


The documentation for the SET command gives no warning of this
whatsoever, but the largest number that can be reached via
calculations with the /A switch is 2,147,483,647, which happens to be
2 raised to the 30th power - 1. Any equation that reaches a total
greater than this will give erroneous results. Another curiousity
about the SET documentation is that it never mentions that /A switch
calculations will always return an integer value. It apparently just
truncates all fractional answers by lopping off (not rounding) the
fractional part of the answer.

Although the documentation for the SET command states that you can use
the /A switch to work with binary, octal and hexidecimal numbers, in
practice this is so flawed that I strongly recommend that you stick
with manipulation of base 10 numbers only. Here are some of the most
glaring problems with working with hex, octal, and binary data via the
SET /A switch:

1) Binary numbers don't work at all. Period. Although the
documentation states that prefixing a valid binary number
with 0b (as in 0b110010) will cause the SET command
to treat it as a binary number, in practice this always
generates an error message. This means that there is no way
to do any manipulations whatsoever with binary numbers.

2) Although you can convert a hexadecimal or octal number to decimal
via the SET command, there is no built-in way to convert a
decimal number to either hex or octal. As mentioned above, you
can't convert at all to or from binary numbers.

3) If you add (or multiply,subtract,divide) two hex numbers
together, the SET command converts the answer to decimal.
There is no such thing as a "hex mode" that would allow you to
manipulate hex numbers and recieve a hex answer.

4)Working with octal numbers is so screwed-up that I don't even
know where to begin. First of all, the notion of a number being
considered octal merely by prefixing it with a 0 is flawed.
This means that perfectly valid decimal numbers like 03, 045,
0132, etc. will automatically be considered as being octal
numbers by the SET command whether you want it to or not.
In addition, this means that all numbers that begin with 0 and
contain either an 8 or 9 will generate a run-time error, since
8 and 9 are not valid octal characters. In addition, the SET
command always converts the results of all calculations
involving octal numbers to decimal. There is no built-in way
to do an octal calculation and receive an octal result.

In addition to all the problems listed above, using parentheses to
group operations together in a SET /A statement invariably generates
an error message, despite what the documentation claims. For example,
SET /A returns an error message if you try something like this:

SET /A answer = (10 - 5) * 8

The bottom line is this: if you need to do serious and accurate
manipulation of numbers from a batch file, don't bother with the SET
command; either shell to QBASIC in your script or use a third-party
ultility.


The FINDSTR command has a curious, serious, and as far as I know,
undocumented flaw. It can only search a maximum string length of 127
characters. Any string passed to it that's longer than that generates
an error message. If you have a fairly lengthy PATH, then type the
command SET|FINDSTR %PATH% at the command prompt and catch the error
message. It's older brother the FIND command has no such limitation,
at least not at that low level.


The maximum length of a WinNT command line is about 2008 characters.


EDIT can be can quite useful as an alternative to a GUI text editor.
For one thing, it does lengthy Find & Replace operations MUCH faster
than Notepad or Wordpad. However, unlike the EDIT command in Windows
95/98, the EDIT command in Windows NT has not been enhanced to handle
long filenames. A command such as the one below will generate an error
message or merely open the help for EDIT.

EDIT "c:\new document.txt"

Here is a workaround for this problem. This solution assumes that your
path includes the %SYSTEMROOT% and %SYSTEMROOT%\SYSTEM32 directories
and that the %SYSTEMROOT%\SYSTEM32 directory is AHEAD of %SYSTEMROOT%
in the path, which is exactly the case unless you reordered your path.
If all is well with the path, then you can do the following:

1) Move (not copy), EDIT.COM from the %SYSTEMROOT%\SYSTEM32
directory to the %SYSTEMROOT% directory.

2) Create a one-line batch file named EDIT.BAT or EDIT.CMD in the
%SYSTEMROOT%\SYSTEM32 directory with the following command
line:

@for %%? in (%1) do %systemroot%\edit %%~ndspx?

Now when you type EDIT "this is a long filename.txt" at a command
prompt, you will actually be passing the long filename to the batch
file, which will in turn launch EDIT.COM, passing it the short
filename equivalent of the long filename.


The Windows NT TYPE command is more versatile than the its Dos\Win9x
counterpart. It can handle multiple filenames on the command line. It
also understands wildcard characters.


The Windows NT FIND command is also more versatile than its Dos\Win9x
counterpart. It can find a search string from multiple filenames on
the command line, and it can handle wilcards used in the filenames.


The IF command has a major feature that was left completely
undocumented. You can use ELSE in conjunction with an IF command to
select from several alternatives. When using ELSE you must place
parentheses around all arguments passed to the IF condition, or your
procedure will either not work correctly or generate an error message.
For example:

if exist myfile.txt (echo yes) else (echo no)

This doesn't work:

if exist myfile.txt echo yes else echo no

You can have multiple IF and ELSE statements in an IF command line,
but only the first TRUE condition will be executed. For example:

if 1==1 (echo 1) else if 2==2 (echo 2) else if 3==3 (echo 3)

The above command line will echo only 1 instead of echoing 1, 2 and 3,
even though the condtions for echoing 2 and 3 are TRUE. That's because
ELSE processes only the first true condition that it sees.

The command line documentation for the IF command states the
following:

If Command Extensions are enabled IF changes as follows:

IF [/I] string1 compare-op string2 command
IF CMDEXTVERSION number command
IF DEFINED variable command

where compare-op may be one of:

EQU - equal
NEQ - not equal
LSS - less than
LEQ - less than or equal
GTR - greater than
GEQ - greater than or equal

These comparisons are generic, in that if both string1 and string2
are both comprised of all numeric digits, then the strings are
converted to numbers and a numeric comparison is performed.

The above is true as far as it goes. The problem arises when an IF
command is wrapped in a FOR command. In that case, string1 and string2
are NOT converted to numbers even if they are comprised of all
numeric digits. Therefore, a numeric comparison is NOT performed.

Having to capitalize the above-mentioned comparison operators (you did
know that, didn't you?) in order for them to work in a procedure
amounts to a bug. I'm aware of no other NT commands that have to be
written in a specific case.


If the first parameter passed to the START command is a quoted string,
then the START command uses that quoted string for the TITLE of the
command prompt window that it opens. It does NOT run the quoted string
as a command. That's why a command line like this gives unexpected
behaviour:

START "%windir%\system32\calc.exe"

One would expect for the above command line to launch the Calculator,
right? Well, it doesn't. Instead, it launches a command prompt with
the command line "%windir%\system32\calc.exe" in its title bar. This
command prompt window stays open until you close it, but the
Calculator never starts. The workaround for this behaviour (which, to
use a famous Microsoft excuse, is by design; take a careful look at
the first few lines of the START command's command-line documentation)
is to rewrite the above command line as follows:

START "1" "%windir%\system32\calc.exe"

The START command will now launch a very brief command prompt window
with 1 in the title bar; it will launch the Calculator and close the
window (which you may not even have noticed). Note that "1" is just a
dummy string being passed to the START command. You can pass any
string as the first parameter as long as it's in quotation marks.

- ed lin

unread,
Sep 21, 1999, 3:00:00 AM9/21/99
to
I would add, a port of EXPR is a good way to math.
I'm sure there are 32-bit versions, but I've been running a gnu port to DOS.
Great little utility.

- ed lin

unread,
Sep 21, 1999, 3:00:00 AM9/21/99
to
Great bit of information!

Thanks, Walter Z.

0 new messages