Mr. Script
Frag Out!
When it comes to sluggish hard drives, this handy script will help keep you moving.
- By Chris Brooke
- 02/01/2003
I’ve been spending a fair chunk of my weekends playing Xbox’s premier
game, Halo, when I should be changing the car’s oil or walking the dog.
In Halo, whenever one of your Marines throws a fragmentation grenade,
he announces it by yelling “Frag out,” thus giving you time to avoid the
blast. What better lead for a column in which the featured script is one
that defragments your hard drives? Besides, who among us hasn’t been tempted,
on occasion, to drop a grenade on a server that’s grinding to a slow crawl
due to a fragmented drive?
Pull Pin…Take Cover
A fragmented drive can cause more problems than simply slow read/write
performance. For starters, the drive hardware has to work harder to retrieve
and write data. In extreme cases, this can shorten the life of your hard
drive. Furthermore, fragmented data takes up more drive space due to disk
cluster sizes. The larger the drive and the larger each cluster, the more
space is wasted. While using NTFS and dynamic disks can mitigate these
issues somewhat, there’s still no substitute for keeping fragmented files
to a minimum. The following script will defrag every drive on the computer
and record the status of each defrag operation in a log file, thus enabling
you to take the “frag out.” (See, I told you I’d make the connection!)
<?xml version="1.0" ?>
<package>
<comment>
DefragDrives.wsf
This script runs the command-line DEFRAG utility via the WScript.Shell
object on each drive of the local computer
</comment>
<job>
<runtime>
<description>
This script defragments all local drives
</description>
<example>
C:\CScript DefragDrives /LogFile:[path
and filename]
</example>
<named
name="LogFile"
helpstring="The path and filename
to write
the defrag report"
type="string"
required="true"
/>
</runtime>
<object id="objShell"
progid="WScript.Shell"/>
<object id="objFSO"
progid="Scripting.FileSystemObject"/>
<script language="VBScript">
<![CDATA[
Option Explicit Dim colDrives, clsDrive,
objFile,
sLogFile, iReturn
sLogFile=WScript.Arguments.Named.Item("LogFile")
Set colDrives = objFSO.Drives
'Open
the log file and enter the date/time
Set objFile = objFSO.OpenTextFile(sLogFile,
8, True)
objFile.WriteLine
objFile.WriteLine Date & " "
& Time & vbCRLF
objFile.Close
For
Each clsDrive in colDrives
If clsDrive.DriveType
= 2 Then '2=Fixed drive
iReturn
= objShell.Run("defrag "
& clsDrive
& " -f", 1,
TRUE)
'Open
the file and write the defrag report
Set objFile = objFSO.OpenTextFile(sLogFile,
8, True)
Select Case iReturn 'Get
the return value
Case 0
objFile.WriteLine
"Drive " & clsDrive
& "
Successfully defragmented."
Case 1
objFile.WriteLine
"Drive " & clsDrive
& "
Defrag can celled manually."
Case 2
objFile.WriteLine
"Drive " & clsDrive
& "
Defrag failed! Command-line error!"
Case 4
objFile.WriteLine
"Drive " & clsDrive
&
" Defrag Failed! Insufficient memory!"
Case 6
objFile.WriteLine
"Drive " & clsDrive
&
" Defrag failed! System error!"
Case 7
objFile.WriteLine
"Drive " & clsDrive
&
" Defrag failed! Insufficient drive space!"
Case Else
objFile.WriteLine
"Drive " & clsDrive
& "
Defrag failed! Unknown error!"
End Select
objFile.Close
End If
Next
]]>
</script>
</job>
</package>
The Select Case section skips a couple of numbers, namely, 3 and 5. These
return codes both correspond to “Unknown Errors.” By structuring the Select
Case section as we have, these (and any other return codes not already
specified) will be picked up by the “Case Else” line, and the script will
notify you that it experienced an “Unknown Error.” No need to explicitly
check for every possible return code.
Those of you who’ve followed this column for any length of time know
that my philosophy is to use the simplest method possible to accomplish
the task at hand. In this case, I’m combining the organizational strength
of the Windows Script Host with the efficiency of the defrag command-line
utility. The result is quite a nice little script that can be scheduled
to run overnight on any or all of your servers to keep drive hardware
humming and disk performance high.
Because the bulk of the functionality comes from shelling to the command
line and running defrag, I chose to only open the log file when I had
something to write to it. Ordinarily, I wouldn’t keep opening and closing
a file over the course of a script. However, because the defrag operation
can take hours for each drive, I didn’t want to leave this file open.
The defrag utility returns a value to the shell object after defragmentation
is complete (or fails). I then use a Select Case statement to determine
the result of the operation and write the data to the log file. This occurs
for every fixed drive connected to the computer—floppies, CD-ROMS, removable
drives, network shares and RAM disks are skipped.
To run this script, simply type this at the command line:
Cscript DefragDrives.wsf /LogFile:c:\logfilename.txt
Over the next few months, I’m going to feature scripts that were created
as a direct result of e-mails I’ve received from readers asking me to
show them how to accomplish a specific task. Most of the topics will be
based upon those e-mails, but there’s still time to make
requests. Just put “Scripting” in the subject line and send them my
way.
About the Author
Chris Brooke, MCSE, is a contributing editor for Redmond magazine and director of enterprise technology for ComponentSource. He specializes in development, integration services and network/Internet administration. Send questions or your favorite scripts to [email protected].