Using the FileSystemObjectLibrary
Working with files and directories is an important basic skill for a scripting administrator. You
need to be able to read text files that might contain a list of computers as well as create text
files that might be used as audit ortrace logs for your scripts. The FileSystemObjectlibrary is
fairly extensive and we can’t possibly review everything here. We’ll focus on a few concepts
that will be used throughout this book.
You can open a text file as follows.
strFile="c:\boot.ini"
Set objFSO=CreateObject("Scripting.FileSystemObject")
Set objTS=objFSO.OpenTextFile(strFile)
With just two lines of code, we’ve openedC:\boot.ini. After we create the basic Scripting.FileSystemObject, we create a text stream object that represents the contents of the file. After the
file is open and the text stream object is created, we can read the file line by line. This is accomplished by using a Do…Whileloop and the AtEndOfStreamproperty.
Do while objTS.AtEndOfStream<>True
Loop
As long as we aren’t at the end of the text file, we will loop through. We now need to read each
line of the file and presumably do something with it. Conveniently, there is a ReadLine
method. If we simply want to read the file and echo back each line, we would use something
like the following code.
Do while objTS.AtEndOfStream<>True
Wscript.echoobjTS.ReadLine
Loop
More than likely, you will want to do something with the information contained in that line.
We prefer to set a temporary variable to hold the line’s contents. This makes it easier to clean
up, manipulate, or validate the text string.
Do while objTS.AtEndOfStream<>True
r=objTS.ReadLine
if InStr(r,"XP") then strData=ProcessPC(r)
Loop
In this little snippet, we search the read line for XPand if it is found, we set strDatato the value
returned from a function in a script called ProcessPC(). When we are finished, we should clean
up after ourselves by calling objTS.Closeto close the text file.
Before we leave OpenTextFile, we will briefly explain the different modes in which a file can be
opened. You can open a file for reading only, for writing, or for appending. You simply specify
the mode as one of the OpenTextFileparameters. This is generally done by defining constants
in your script, as shown here.
Const FORREADING=1
Const FORWRITING=2
Const FORAPPENDING=8
strFile="c:\boot.ini"
Set objFSO=CreateObject("Scripting.FileSystemObject")
Set objTS=objFSO.OpenTextFile(strFile,FORREADING)
If you open a file for writing, any existing data will be overwritten. If you open a file for
appending, any data you write will be added to the end of the file. If you open a file for reading
only, no changes can be made to the file. We generally use OpenTextFilefor reading or appending. If we need to write new data, we use the CreateTextFilemethod, as shown here.
strFile="c:\logs\myaudit.log"
Set objFSO=CreateObject("Scripting.FileSystemObject")
Set objTS=CreateTextFile(strFile,TRUE)
objTS.WriteLine "Audit log: " & Now
'script continues
With the addition of a CreateTextFileparameter, the code is pretty simple. When this parameter is set to TRUE, any existing file with thatname will be overwritten. If you don’t include
a CreateTextFileparameter, existing files will not be overwritten, and your script won’t get
very far unless you add some error handling. But after we’ve created the text file, we use the
WriteLinemethod to add whatever data we want. As before, when we are finished, we need to
close the file with objTS.Close.
The other common use of the FileSystemObjectis for working with folders and files. Listing
FileSystemObjectFile Sample
On Error Resume Next
Dim objFSO,objFldr,objFiles,objTS
strTitle="File Demo"
strDir=InputBox("What folder do you want to examine?",_
strTitle,"c:\files")
If strDir="" ThenWScript.quit
Set objFSO=CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists(strDir) Then
'open folder
Set objFldr=objFSO.GetFolder(strDir)
'get log file information by calling
'the GetFileName function
strFile=GetFileName
If strFile="" Then
WScript.Quit
Else
'call validation subroutine
ValidateFile strFile
End If
Else
WScript.Echo "Can'tfind " & strDir
WScript.Quit
End If
objTS.WriteLine "Folder Report for " & strDir
'get files in this folder
'objFiles is a collection
Set objFiles=objFldr.Files
'initialize our counter
i=0
'set variable for total number of files in folder
t=objFiles.Count
'enumerate the collection of files
For Each file In objFiles
'get file information and write to log file
objTS.WriteLine file.Name & vbTab & file.size & " bytes" & vbTab &_
file.DateCreated & vbTab & file.DateLastModified
i=i+1
iPer=FormatPercent((i/t))
WScript.StdOut.Writeline(iPer& " complete")
Next
18 Part I: The Basics of Advanced Windows Scripting
'close file
objTS.Close
MsgBox "See " & strFile & " for results.",vbOKOnly+vbInformation,strTitle
WScript.Quit
'////////////////////////////////////////////////////////////////////////
Function GetFileName()
On Error Resume Next
GetFileName=InputBox("What is the name of theaudit file you " &_
"want to create?",strTitle,"c:\filelog.txt")
End Function
'////////////////////////////////////////////////////////////////////////
Sub ValidateFile(strFile)
On Error Resume Next
'check if log file exists and if so
'prompt user if they want to overwrite.
If objFSO.FileExists(strFile) Then
rc=MsgBox(strFile & " already exists. Do you want " &_
"to overwrite it?",vbYesNoCancel+vbQuestion,strTitle)
Select Case rc
Case vbYes
WScript.Echo"Overwriting file" & strFile
Err.Clear
'create our logfile by overwriting
Set objTS=objFSO.CreateTextFile(strFile,True)
IfErr.Number<>0 Then
strMsg="There was an error creating " &_
strFile & VbCrLf & "Error#" & Err.Number &_
" " & Err.Description
MsgBoxstrMsg,vbOKOnly+vbCritical,strTitle
WScript.Quit
End If
Case vbNo
strFile=GetFileName
ValidateFile strFile
Case vbCancel
WScript.Echo "Aborting the script"
WScript.Quit
End Select
Else
'create our log file
Err.Clear
Set objTS=objFSO.CreateTextFile(strFile)
If Err.Number<>0 Then
strMsg="There was an error creating " &_
strFile & VbCrLf & "Error#" & Err.Number &_
" " & Err.Description
MsgBox strMsg,vbOKOnly+vbCritical,strTitle
WScript.Quit
End If
End If
End Sub
If you’ve been reading from the beginning of this chapter.
includes a lot of the suggestions and tips made earlier, plus a little something extra to reward
you for getting this far in the chapter.
Listing 1-12 examines all the files in a specified folder and creates a log with specific file information. This common use of the FileSystemObjectworks with any local or mapped drives, as
well as Universal Naming Convention (UNC) paths. The script starts by asking the user for
the folder path to examine.
strDir=InputBox("What folder do you wantto examine?",_
strTitle,"c:\files")
Assuming the user entered something, we can use the FolderExistsmethod to validate the
entry.
If objFSO.FolderExists(strDir) Then
'open folder
Set objFldr=objFSO.GetFolder(strDir)
...
We want a log file for the audit results, and now that we know we can continue, we need to
create a text file. Recall that typically a function returns a value,and a subroutine is a section
of modularized code that you can call as needed. We need to get the name of the log file from
the user, so the script has a function called GetFileNamethat works as an InputBoxwrapper.
Function GetFileName()
On Error Resume Next
GetFileName=InputBox("What is the name of theaudit file you " &_
"want to create?",strTitle,"c:\filelog.txt")
End Function
Again, assuming the user entered something, we need to validate the logfile. We call the
ValidateFilesubroutine that takes a file name as a parameter. If the file already exists, we ask
the user if he or she wants to overwrite the file.
If objFSO.FileExists(strFile) Then
rc=MsgBox(strFile & " already exists. Do you want " &_
"to overwrite it?",vbYesNoCancel+vbQuestion,strTitle)
Depending on the answer, we can either create the text file and overwrite the existing version
or prompt the user to specify a new log file name.
Select Case rc
Case vbYes
WScript.Echo "Overwriting file " & strFile
Err.Clear
'create our logfile by overwriting
Set objTS=objFSO.CreateTextFile(strFile,True)
If Err.Number<>0 Then
strMsg="There was an error creating " &_
strFile & VbCrLf & "Error#"& Err.Number &_
20 Part I: The Basics of Advanced Windows Scripting
" " & Err.Description
MsgBox strMsg,vbOKOnly+vbCritical,strTitle
WScript.Quit
End If
Notice the error handling in case there is a problem overwriting the file. If the user clicks No,
we call the GetFileNamefunction again and then call the ValidateFilesubroutine, basically
rerunning the code.
Case vbNo
strFile=GetFileName
ValidateFile strFile
Of course the user could tire of this and click Cancel, in which case we simply exit the script.
Case vbCancel
WScript.Echo "Aborting the script"
WScript.Quit
End Select
If the file doesn’t exist, we create it and returnto the main part of the script. Again notice the
error handling and MsgBox.
'create our log file
Err.Clear
Set objTS=objFSO.CreateTextFile(strFile)
If Err.Number<>0 Then
strMsg="There was an error creating " &_
strFile & VbCrLf & "Error#" & Err.Number &_
" " & Err.Description
MsgBox strMsg,vbOKOnly+vbCritical,strTitle
WScript.Quit
End If
Now that we have the audit log taken care of, let’s get down to business and use the FileSystemObjectto look at the files in the folder. We createa collection object that will represent all the
files in the folder by calling the Filesmethod.
Set objFiles=objFldr.Files
We can enumerate this collection with a For…Each…Nextloop and write information about
each file to the log.
For Each file In objFiles
'get file information and write to log file
objTS.WriteLine file.Name & vbTab & file.size & " bytes" & vbTab &_
file.DateCreated & vbTab & file.DateLastModified
i=i+1
iPer=FormatPercent((i/t))
WScript.StdOut.Writeline(iPer& " complete")
Next
Chapter 1: Getting Started 21
The FileSystemObjectexposes file properties such as its name; its size; the date it was created,
modified, and accessed; and a few others. This script creates a tab-delimited file, but it could
easily be a comma-separated value (CSV) log instead.
After we’ve finished examining every file in the folder, we close the log file and display a completion message to the user.
objTS.Close
MsgBox "See " & strFile & " for results.",vbOKOnly+vbInformation,strTitle
By the way, the script as written does not recurse through any subfolders. We’ll leave that as
an exercise for you. But there’s one more goody in this script—we added code to provide some
progress feedback to the user. The only catch isthat you must run the script from a command
line using CScript.
There is a Countproperty for our files collection that will show the number of files in the
current folder. If we know the total number of files and the number of files processed, we can
calculate the percentage complete. We just need some variables.
'initialize our counter
i=0
'set variable for total number of files in folder
t=objFiles.Count
In the For…Eachloop, we increment our counter variable and calculate the percent complete.
We use the FormatPercentfunction to tidy up the math.
i=i+1
iPer=FormatPercent((i/t))
All that is left is to display the result. We’ve decided to use the StdOutmethod of the Wscript
object to write directly to the command prompt window.
WScript.StdOut.Writeline(iPer& " complete")
The method will not work if the script is run with WScript. It must be run with CScript at a
command prompt by typing cscript listing1-12.vbs. The percent complete scrolls down the
screen, informing the user about how the script is progressing.