In "Gathering File System Data" (November 2006, InstantDoc ID 93451), I presented aWindows Script Components (WSC) object, FileDB .wsc, that saves information about files to a comma-separated values (CSV) text file. I created the component after a user accidentally deleted a file on the server. A catalog-searching tool would have been extremely helpful in finding the file on the backup tape, but I was forced to browse manually through thousands of files and folders because NTBackup doesn't provide a way to search a backup catalog.
To save time in the future, I decided to write a script that could use the FileSystemObject object to iterate through one or more folders, build a list of files, and save the list to a CSV file. This month, I present NTCatalog.js, which uses the FileDB.wsc component to catalog an NTBackup .bks file's information to a CSV file.
Backup Selection Files
When you schedule an NTBackup job, the backup utility creates a Unicode text file that has a .bks extension and contains the names of files and folders to include in (or exclude from) the backup. You can also create a .bks file manually by selecting files and folders in the NTBackup window and choosing the Save Selections option from the Job menu.
Each line of a .bks file starts with either a filename or a folder name. (This rule has two exceptions, which I'll explain in a moment.) If the file or folder is to be excluded from the backup, the line ends with the string /Exclude. When the line contains a filename, NTBackup backs up that specific file. (NTBackup doesn't support wildcard backups, such as C:\Folder\*.doc.) When the line contains a folder name, NTBackup backs up all files in that folder. In both cases, NTBackup backs up files in subfolders as well. For example, if your .bks file contains the line C:\Docs\file.doc, NTBackup will back up C:\Docs\File.doc, but also all other files named file.doc that exist in subfolders of C:\Docs.
Figure 1 shows a sample .bks file. To allow NTBackup to differentiate between folders and files, folder names must be followed by a backslash (\). When a name isn't followed by a backslash, NTBackup treats the name as a filename.
If NTBackup were using this sample file, the utility would back up everything on the C drive and everything in the Shares folder on the D drive. The utility wouldn't back up the Videos folder in the Shares folder, nor the subfolders under Videos. But it would back up a file named CompanyIntro.mpg in the Videos folder and in all subfolders of the Videos folder.
As I stated earlier, there are two exceptions to the rule that each line in a .bks file must contain a folder name or a filename. First, if the string SystemState appears on the last line, NTBackup backs up the system state. Second, a .bks file can also specify that Exchange Server be backed up. In this case, the syntax depends on the version of Exchange. For example, for Exchange Server 2003, the syntax looks like this:
JET servername\Microsoft Information Store\First Storage Group\
where servername is the name of the Exchange server.
The .bks Unicode File Format
You need to know one more thing about working with .bks files. As I've said, a .bks file is Unicode text.
However, you can't save .bks files properly with Notepad because Notepad prefixes Unicode text files with a byte-order marker, which NTBackup doesn't understand.
The following workaround can help. To create your own .bks file, create it as ANSI or ASCII text instead of Unicode. After saving the file, use cmd.exe's /u option to type the filename and redirect the file to a Unicode text file. For example, to save the file selections.txt to selections.bks, type the following command all on one line at a command prompt:
cmd /u /c type selections.txt > selections.bks
The /u option tells cmd.exe that the output from its internal commands should be Unicode. The /c option executes the remainder of the line as a command. The Type command sends the selections.txt file to standard output, which is then redirected to the selections.bks file. Because Type is an internal command, the selections.bks file will be in Unicode format. Cmd.exe doesn't create a byte-order marker at the beginning of Unicode files, so you can use cmd.exe with the /u option to convert a plaintext file containing backup selections to a valid .bks file.
If you create your own .bks file, remember to append a trailing backslash when you specify a folder. If you don't, NTCatalog.js will think that the line refers to a file. For example, if you intend to back up the folder C:\ Program Files, make sure that you type
C:\Program Files in the .bks file.
NTCatalog.js opens a .bks file and creates a CSV file that contains the names of all files selected for backup. The script requires the FileDB.wsc component, so before you can use NTCatalog.js, you need to obtain FileDB.wsc and register it on your computer. You can download FileDB.wsc from the Windows Scripting Solutions Web site at http://www.windowsitpro.com/windowsscripting, InstantDoc ID 93451.
NTCatalog.js requires the CScript host, so you need to start the command line with the CScript keyword if CScript isn't the default host. To configure CScript as your default host, type the following command at a command prompt:
cscript //h:cscript //nologo //s
The syntax for NTCatalog.js is
\[cscript\] NTCatalog.j s bksfile csvfile \[/n\]
where bksfile is the name of the .bks file and csvfile is the name of the CSV file that the script should create. If either filename contains spaces, put the filename in quotes.
By default, the CSV file will be overwritten if it already exists. If you don't want to overwrite an existing file and prefer to generate an error message instead, add the /n option to the command line.
Listing 1, shows an excerpt from NTCatalog.js. The script begins by defining some global variables, then executes the main function, which provides most of the script's functionality. The return value of the main function is the script's exit code.
The main function declares some local variables, then determines whether it was executed with at least two command-line arguments. If there are fewer than two arguments, or if the /? argument is present, the main function executes the usage function, which displays a short usage message and ends the script. Otherwise, the main function uses the scriptHost function to determine the name of the script host executing the script. If the script host isn't cscript.exe, the main function echoes an error message to the screen and ends with a non-zero exit code.
When the script host checks out, the main function creates an instance of the FileSystemObject object and uses it to verify the existence of the .bks file. If the .bks file doesn't exist, or if the /n option was specified on the command line and the output file already exists, the script ends with a non-zero exit code.
Next, the code at callout A creates an instance of the FileDB object. The code then opens the .bks file, as callout B shows. Note that the Open-TextFile method's fourth parameter is true, indicating that the .bks file is a Unicode text file.
At this point, the .bks file has been opened as a TextStream object, and the main function can loop through the file, which it does by using the While statement. As long as the AtEndOfStream property is false (indicating the end of file has not been reached), the loop will continue.
Inside the While loop, the main function reads a line of text and uses the search method at callout C to determine whether the line ends with the string " /exclude" (including the leading space, but not including the quotes). The search method's parameter is a regular expression that specifies the pattern to search for. The search method returns a number indicating the pattern's starting position inside the string. If the pattern isn't found, the search method returns the value -1 in the pos variable. (The trailing "i" after the closing "/" in the regular expression specifies a case-insensitive match.)
The main function then checks the value of the pos variable. When the value isn't -1, the function verifies that the line references an existing file or folder, then uses the FileDB object's Include method to add that file or folder to its internal Recordset object. When NTBackup backs up folders, it always backs up subfolders as well, so the Include method's Recurse parameter has the value true.
When the line contains the name of a file or folder that's to be excluded from backup, the main function uses the substring method at callout D to extract a copy of the string that doesn't include the " /exclude" portion. The function then determines whether the extracted substring specifies an existing file or folder. When it does, the main function calls the FileDB object's Exclude method to remove matching files from FileDB's Recordset. Because NTBackup always excludes subfolders of folders that it doesn't back up, the Exclude method's Recurse parameter is also true.
After each line of the .bks file has been read and processed, the main function closes the TextStream object and calls the FileDB object's WriteCSV method to create the CSV file.
Using the Script
You can use NTCatalog.js as part of your scheduled backup routine to create a CSV file containing the names of files to be backed up. Later, if you need to search for a file in a backup set, you can import the CSV file into a database tool and quickly find what you're looking for, saving time and energy.