Here's the script (so far). Note that it requires a S_CONFIG and S_BIN environment var to be set. All the servers here at home have a "customize" script run on them that creates a /local folder (S_CONFIG) for config files, a /local/bin (S_BIN) for all the scripts and utilities, and adds the S_BIN folder to the path, and a few other tweaks.

The DEFRAG.INI file is simple:
[COMMON]
Services=UPS,spooler,etc... - services to stop during defrag
PRECMD=command to run before defragging
POSTCMD=command to run after defragging
[FileSys]
Path=C:\

Create as many unique FileSys definitions as needed to define your volumes. The COMMON section is completely optional. I only use it to stop the Exchange server services. It doesn't seem to be necessary, but seems to be a bit faster.

Code:
;; KixGenerated: 2005/11/23 - 13:36:03 
; Defrag.kix - Utility to manage scheduled defrag processes using the native Windows tools
; Glenn Barnas
; 2005/11/23

Break On

Dim $, $IFile, $Services, $Service, $PreCommand, $PostCommand, $Path, $LFile, $Cmd
Dim $Volumes, $Volume

$ = SetOption('Explicit', 'On')
$ = SetOption('WrapAtEOL', 'On')
$ = SetOption('NoVarsInStrings', 'On')

If %S_CONFIG% = ''
? 'System not customized! Aborting!' ? ?
Exit 1
EndIf

$IFile = %S_CONFIG% + '\defrag.ini'
$LFile = %S_CONFIG% + '\Logs\defrag.log'
Del $LFile

; Get the COMMON parameters from the ini file
$Services = ReadProfileString($IFile, 'COMMON', 'Services')
$PreCommand = ReadProfileString($IFile, 'COMMON', 'PreCmd')
$PostCommand = ReadProfileString($IFile, 'COMMON', 'PostCmd')

; Stop the defined services
If $Services
'Stopping services' ?
For Each Trim($Service) in Split($Services, ',')
Shell 'Net Stop "' + $Service + '"'
Next ; service
EndIf ; services

; Run the PreCmd if defined
If $PreCommand
'Running pre-init command.' ?
Shell $PreCommand
EndIf

; Enumerate the INI file to determine which volumes to defragment - ignore the COMMON section
$Volumes = EnumIni($IFile)
For Each $Volume in $Volumes
If $Volume <> 'COMMON'
$Path = ReadProfileString($IFile, $Volume, 'Path')
$Cmd = %COMSPEC% + ' /c ' + %SYSTEMROOT% + '\System32\defrag.exe ' + $Path + ' >> ' + $LFile
;$Cmd = %SYSTEMROOT% + '\System32\defrag.exe ' + $Path
' ' $Cmd ?
$ = RedirectOutput($LFile)
@DATE ' ' @TIME ' Starting defrag of ' $PATH ?
$ = RedirectOutput('')
Shell $Cmd
$ = RedirectOutput($LFile)
@DATE ' ' @TIME ' Complete - ' @SERROR ? ?
$ = RedirectOutput('')
EndIF

Next ; volume

; Run the PostCmd if defined
If $PreCommand
Shell $PostCommand
EndIf


; Start the defined services
If $Services
For Each Trim($Service) in Split($Services, ',')
Shell 'Net Start "' + $Service + '"'
Next ; service
EndIf ; services


$ = RedirectOutput($LFile)
? @DATE ' ' @TIME ' Defrag of @WKSTA is complete!' ?
'============================================================' ? ?
$ = RedirectOutput('')


;;
;;======================================================================
;;
;;FUNCTION EnumIni()
;;
;;ACTION Enumerates sections or keys of an INI file
;;
;;AUTHOR Glenn Barnas
;;
;;VERSION 2.0
;;
;;DATE CREATED 2003/11/17
;;
;;DATE MODIFIED 2004/10/16
;;
;;SYNTAX EnumIni($File [, $Section])
;;
;;PARAMETERS $File - REQUIRED, path/name of INI file to examine
;;
;; $Section - OPTIONAL, Section name to parse
;;
;;REMARKS Returns an array containing the sections in an INI file, or
;; an array of key names in a specified section. Errors are returned
;; for non-existant files or INI file reads. If the specified file
;; contains no sections, or the specified section contains no keys,
;; the UDF exits with error 13 and returns a null array. Thus, a For-Each loop
;; will properly perform no iterations if no data is returned.
;;
;; CAUTION - Error 13 is returned for empty files, or nonexistant sections.
;; This is not necessarily a "failure".
;;
;;RETURNS Array of sections or keys in a section
;;
;;DEPENDENCIES none
;;
;;TESTED WITH Kix 4.2+, NT4, W2K, WXP, W2K3
;;
;;EXAMPLES $Sections = EnumIni('.\config.ini')
;; $Keys = EnumIni('.\config.ini', 'Common')
;
Function EnumIni($_fSrcFile, OPTIONAL $_fSectName)

Dim $_fSectList

; die if the file doesn't exist
If Exist($_fSrcFile) = 0
Exit 2
EndIf

; Get the list of sections or keys
$_fSectList = ReadProfileString($_fSrcFile, $_fSectName, '')
; Return if error occurred
If @ERROR
Exit @ERROR
EndIf

; If len is >0, return an array of sections
; If len is 0, either no sections or keys exist, or an invalid section name was specified. Return nothing.
If Len($_fSectList) > 0
$EnumIni = Split(Left($_fSectList,len($_fSectList)-1), Chr(10))
Exit 0
EndIF

; return an error here for value not found (no sections or no keys in section)
Exit 13

EndFunction

_________________________
Actually I am a Rocket Scientist! \:D