Downloads
15848.zip

Windows NT Shell Scripting—Intermediate

Most systems administration scripts fall into three categories: report creation, administrative operations, or notification. This month, I present a useful notification script, BlatDirTest.bat, and show you three scripting techniques:

  • How to use Blat to send email messages from a Windows NT shell script
  • How to use the For and Set commands to count loops
  • How to retain a script's returned results

The Scenario
Suppose that several senior managers in your company now have the permissions they need to create top-level folders on a public share. You need to write a script that checks the number of folders on the public share twice a day and, if that number changes, sends systems administrators an email message stating the change.

Using Blat
Scripts often notify someone about an event or condition that they detect. The easiest notification tool to use is the Net Send command, which sends an NT messenger-service message to the specified computer or user. Net Send, however, has limitations. If the specified computer is turned off or the specified user isn't logged on, the message fails. If the user is typing and hits the space bar or Enter key when the message arrives, the messenger service window closes and the message is lost, perhaps before the person read or even noticed it. Because of these limitations, sending an email message is a much better alternative.

Scriptwriters commonly use Blat in NT shell scripts to send email and pager messages that go through an email-enabled paging service vendor. Blat is public-domain utility available at http://www.interlog.com/ ~tcharron/blat.html.

You can access Blat's run options by typing

Blat h

at the command line. BlatDirTest.bat uses the basic syntax

Blat C:\blat.txt -s
        "Subject line here"
        -t recipient@company.com
        -f sender@company.com

to send either an email or pager message.

Email message. If you're sending an email message, you specify the email message's Subject line ("Subject line here"), the email address of the intended recipient (recipient@company .com), and the email address of the person sending the email message (sender@company.com). The input file blat.txt contains the text of the email message. (If you want, you can rename the input file.) Because the text includes data that the script produces, BlatDirTest.bat uses the Echo command to create the input file on the fly. Another option is to use stock text (i.e., text that doesn't vary between email messages) to describe the event or condition. In this case, you create the input file and specify the stock text before running the script.

Pager message. If you're sending a pager message, you specify the email address of the paging service vendor (recipient@company.com) and the email address of the person sending the email message (sender@company .com). In the "Subject line here" field, you specify the stock text instead of a Subject line. Although no text goes into blat.txt, you must still create a blank input file. Otherwise, Blat won't work.

Using the For Command
The For command is versatile. Scriptwriters often use this command to parse another command's output into pieces for manipulation. Take, for example, the Dir command

Dir /ad /b C:\TestFolder

This command returns all the folders in the C:\TestFolder directory in a format similar to the one that Figure 1 shows. However, if you use the For command with the Dir command

For /f "Tokens=*" %i in
('Dir /ad /b C:\TestFolder')
Do Echo %i

you break up the Dir command's results into pieces like the ones that Figure 2 shows.

In BlatDirTest.bat, you're not interested in obtaining the names of the folders but rather the number of folders. To obtain that number, you can combine the For command just given with a subroutine (i.e., :Increment) that uses a Set /a command math operation to count the number of pieces that the For command parses. Listing 1 contains this combined code called Test.bat.

In Test.bat, the Set command's /a switch ensures that the string in the %Counter% variable is a numeric expression. The %Counter% variable increments by 1 each time the For command calls the :Increment subroutine. When the For command finishes looping through the Dir command's results, the last value in the %Counter% variable is the number of folders. In this case, that value is 4, as Figure 3 shows.

Test.bat is highly adaptable. For example, if you change the Dir command's /ad switch to /a-d, the code counts the number of files instead of folders. If you change the For command to

For /f "Tokens=3" %i in
('Dir /s /-c C:\TestFolder
^| Find "File(s)"') Do Echo %i

the code tracks the number of bytes in a directory's files. If you make adaptations, keep in mind these important points about the Set command:

  • You must use the /a switch anytime you want to perform math functions with string values.
  • You can't use uninitialized values. For example, the code Set /a Counter=%Counter%+1

    returns an Operand Missing error message. You must initialize the %Counter% variable to 0 with code such as

    Set Counter=0
  • The Set /a command can't handle values that have more than 10 digits. If you're dealing with large numbers, you need to use a language (e.g., Perl) that can better handle them.
  • When the Set /a command performs division, it rounds the results down to the next integer.

For more information about the Set /a command math operations, see Tim Hill, Windows NT Shell Scripting (Macmillan Technical Publishing, 1998).

Retaining the Results
You can retain a script's returned results several ways, including writing, or echoing, the results to a file, the Registry, or an NTFS data stream. In BlatDirTest.bat, you echo the results (i.e., the number of folders that BlatDirTest.bat detects) to an NTFS data stream. Files (and even folders) in an NTFS file system can support multiple data streams. NTFS files have a visible unnamed stream that contains the data that you view when you open a file in an editor. NTFS files have additional hidden named streams in which you can place usable data. In the article "How to Take Advantage of the Hidden Streams in Your Scripts," page 1, I describe how to create and use these hidden streams.

As Table 1 shows, the code for echoing results to a hidden stream is similar to the code for echoing results to a file. In both cases, you specify the file to which you want to echo the script results. Typically, you echo the results to the .bat file you're executing; however, you can choose any file that isn't prone to accidental deletion. The code to echo results to a hidden stream differs from the code to echo results to a file in one important respect: The former includes a stream name. To open a hidden stream in Notepad, you put the filename and stream name together in the format Filename:StreamName.txt. Although stream names are case insensitive, they can't include any spaces.

In the Filename:StreamName combination, you can substitute the value of %0 for Filename and the value of %1 for StreamName, respectively, if you want to make the code cryptic to prying eyes. Or, you can substitute just one of the values. However, if you have a Windows 2000 system, don't use the %0 value because Win2K places double quotes around it, which cause the value to function incorrectly.

Whether you echo a number to a file or a hidden stream, you must place a space between that number and the redirect (> or >>) character. The command

Echo 0>C:\test.txt

will fail, but the command

Echo 0 >C:\test.txt

will function properly.

Using BlatDirTest.bat
Listing 2 contains an excerpt from BlatDirTest.bat. (You can find the entire script in the Code Library on the Win32 Scripting Journal Web site at http://www.win32scripting.com/.) The script includes comments to help you understand the code. To get BlatDirTest.bat working in your environment, follow these steps:

  1. Download and install Blat. To copy blat.exe to your \system32 folder, use the command
    Blat -install
    smtpserver.company.com
    username@company.com

    where smtpserver.company.com and username@company.com are specific for your system. Include the username only if your SMTP server requires it. If your mail server uses a nonstandard port for SMTP, consult the readme.txt file for the proper installation command. This file also contains configuration examples.

  2. Copy BlatDirTest.bat to the server or workstation on which you'll schedule the script to run.
  3. Configure the target directory you want to track. Callout A in Listing 2 highlights the code you need to configure.
  4. Configure the Subject line, the recipient's email address, and the sender's email address. Callout B in Listing 2 highlights the code you need to configure.
  5. If you're running Win2K, perform a search-and-replace operation to replace the %0 values in the script with the appropriate filename.
  6. Run the script to load the number of folders value into the hidden stream.
  7. Run the script again. The recipient won't receive an email message.
  8. Add an empty folder to the target directory, and run the script again. The recipient will receive an email message stating the old number of folders and the new number of folders.
  9. Use the Task Scheduler to schedule BlatDirTest.bat.

I tested BlatDirTest.bat on Win2K Professional and NT Server 4.0 Service Pack 6a (SP6a). You must have an NTFS partition to use this script.