Subscribe to Windows IT Pro
October 08, 2004 12:00 AM

Extending Windows XP’s Disk Defragmenter

XDefrag to the Rescue
Windows IT Pro
InstantDoc ID #43924
Rating: (0)
Downloads
43924.zip

Disk defragmentation is an important aspect of routine system maintenance. Windows 2000 provides a built-in defrag utility that can be started only by an administrator using Microsoft Management Console (MMC). To automate this utility, you must send keystrokes to the GUI—a process that can be awkward and error-prone. Windows XP and later includes a command-line defrag utility called Disk Defragmenter (defrag.exe) that's much easier to automate. However, Disk Defragmenter isn't without limitations. For example, you can execute it on only one volume at a time—it won't run on multiple volumes simultaneously. In addition, you can specify only one volume name at a time and the utility sends output to the command window only.

I wrote a VBScript script called XDefrag that works around some of these problems and extends the usefulness of Disk Defragmenter. XDefrag provides the following value-added features:

  • It lets Disk Defragmenter sequentially defrag multiple volumes.
  • It lets Disk Defragmenter sequentially defrag all local fixed drives, without having to create different batch files for different computers if there are different local fixed drive letters.
  • It can record all status information in the Application event log. Each report contains a start time, end time, elapsed time, and exit code.

You can find XDefrag on the Windows Scripting Solutions Web site. Go to http://www.windowsitpro.com/windowsscripting, enter InstantDoc ID 43924 in the InstantDoc ID text box, then click the 43924.zip hotlink. Before you download this script, though, you should know how to run it and how it works. Specifically, it helps to understand how the Main subroutine, DefragVolume function, and Elapsed function work.

Running XDefrag
There are only two requirements to run XDefrag. First, your machines must be running XP or later. Second, you must use Windows Script Host's (WSH's) CScript to run XDefrag because the script sends its output to the command window. From that point, you can redirect the script's output to a file if desired.

To set CScript as the default host, enter the following command on the command line:

cscript //h:cscript //nologo //s

XDefrag and all your other scripts will then automatically run under CScript. Alternatively, if you want to use CScript for just this script, you can preface the script's launch command with cscript.exe.

The command to launch the script uses the following syntax:

xdefrag.vbs {/L | volume [...]}
  [/E] [/A] [/F] [/V]

(Although this command appears on several lines here, you would enter it on one line in the command-shell window. The same holds true for the other multiline commands in this article.) If you specify the /L switch, the script will sequentially process all local fixed drives. Or, you can specify one or more volumes, where volume can be in the format d: or d:\volume\mountpoint. If you specify two or more volumes, the script will process them sequentially.

The /E switch tells the script to record its activities in the Application event log. If defrag returns a nonzero exit code, the event log will show an error. Figure 1 shows a sample event-log entry. The script's /A, /F, and /V switches are the same as the Disk Defragmenter's options of -a (analyze only), -f (force defragmentation, even if free space is low), and -v (verbose output), respectively.

To schedule the script to run, you can use the Scheduled Tasks window or use the Schtasks command. In either case, because the script requires CScript, I recommend specifying cscript.exe as the executable when creating the scheduled task because CScript isn't the default scripting host on a fresh OS install. If you specify cscript.exe as part of the command, you'll avoid the potential problem of the command not doing what's expected because WScript is executing it. If you were to run the Schtasks command

schtasks /create
  /ru administrator
  /rp password /sc DAILY
  /tn Defrag_Local_Drives /tr
  "%SystemRoot%\system32\cscript.exe
  C:\scripts\xdefrag.vbs
  /E /L /F /V" /st 02:00:00

the current computer will be configured to run a task called Defrag_Local_Drives daily at 2 a.m. The /ru and /rp options specify the credentials under which the task should run, so you need to customize administrator and password to use this command. The string after the /tr switch specifies the command to execute. Note that because the command contains spaces, you must enclose it in quotes.

One advantage to using the Schtasks command is that it can create scheduled tasks on remote computers, so you can construct a batch file to automate scheduled deployment to multiple systems. For more information about how to use the Schtasks command, type

schtasks /?

Inside the Main Subroutine
XDefrag starts by declaring a set of global variables, then calls the Main subroutine. The script's main body exists in the Main subroutine, which has a local scope, rather than in code that has a global scope. All global variables use the g_ prefix to distinguish them from local variables.

As Listing 1 shows, the Main subroutine first calls the ScriptHost function to determine the name of the executable that started the current script. If it isn't CScript, the script exits with an error message.

To parse the command-line arguments, the Main subroutine takes advantage of the WScript.Arguments.Named and WScript.Arguments.Unnamed collections. The Named collection contains named command-line arguments (i.e., arguments that start with a forward slash) and WScript.Arguments.Unnamed contains unnamed arguments (all other arguments). When a named argument exists, the Exists method returns a value of True. In keeping with standard conventions, the script exits with a short usage message when the /? option is present on the command line.

As callout A shows, the Main subroutine checks to see whether the /L switch exists on the command line. If so, the subroutine calls the LocalFixedDrives function. This function returns a collection of local fixed drives by iterating the FileSystemObject object's Drives collection, checking the DriveType property for each drive in the collection, and building a semicolon-delimited list of fixed drives. When exiting, the LocalFixedDrives function calls VBScript's Split function to return an array, which can be iterated the same way as a collection.

If the command line doesn't contain /L, the Main subroutine assigns the Unnamed collection to the colVolumes variable. If this collection's Count method returns a value of 0, the command line contains insufficient information to continue and the script exits with an informational error message.

Next, the Main subroutine populates a Scripting.Dictionary object, as callout B in Listing 1 shows. The DefragVolume function uses the Dictionary object in its report output. This object contains Disk Defragmenter exit codes and a textual description of each one. For more information about the exit codes, see the Microsoft article "How to Provide Event Logging for the Disk Defragmenter Utility with Windows Script Host" (http://support.microsoft.com/?kbid=294743).

Finally, the Main subroutine processes the volumes sequentially by iterating through the colVolumes collection and passing each member of the collection to the DefragVolume function. The script's exit code will be the highest exit code returned by all calls to DefragVolume.

Related Content:

ARTICLE TOOLS

Comments
    There are no comments to display. Be the first one!
You must log on before posting a comment.

Are you a new visitor? Register Here

advertisement

advertisement

Windows is a trademark of the Microsoft group of companies. Windows IT Pro is used by Penton Media Inc. under license from owner.