Tuesday, 1 July 2014

Using the FileSystemObjectLibrary

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.

No comments:

Post a Comment