File manipulation is a daily activity for both administrators and developers. Until recently, Windows users had only batch-file commands to help with this important task. Fortunately, the Windows Scripting Host (WSH) environment is now available for all Win32 platforms as an add-on or an installable part of the OS. WSH represents a significant step in automating administrative and repetitive tasks. WSH supports COM automation, which lets users wrap functional code—including code to manipulate files—in an easy-to-use component.
Despite the importance of file manipulation, the WSH object model doesn't include objects to manipulate files. However, you don't have to create a nonstandard object, buy a third-party object, or rely on batch-file commands. Instead, you can use the Microsoft Scripting Run-Time Library's FileSystemObject object.
The FileSystemObject object is the root object of the FileSystemObject (FSO) object model—a hierarchy of COM objects that manipulate the Windows file system. You probably already have the FSO object model installed on your system. The Scripting Run-Time Library comes with Microsoft Internet Explorer (IE) 4.0 or higher. This library also comes with any VBScript or JScript parser and with any version of WSH (2.0 or 1.0). However, the FSO object model is separate from the WSH object model and the core VBScript or JScript functions and objects. This setup embodies Microsoft's philosophy of creating a minimal core WSH structure that can interact with any number of separate object models.
The FSO Object Model
The FSO object model presents drives, folders, and files as COM objects with properties, collections, and methods. You can perform all the tasks that you accomplished with batch-file commands and more. You can copy, move, delete, and rename files. You can enumerate a folder's contents, check the amount of free space in a drive, determine a file's size and modified date, and perform many other useful tasks.
The FSO object model includes the FSO objects in Table 1 and the FSO collections in Table 2. (Table 1 doesn't include the Dictionary object. Although this object is part of the Scripting Run-Time Library, it's not directly related to FSO. Thus, I'll cover the Dictionary object in a future column.) To access the objects and collections representing your system's drives, folders, and files, you must first access the FileSystemObject object.
Accessing the FileSystemObject Object
To start working with any object or collection in the FSO object model, you need to create an instance of the FileSystemObject object. As I discussed last month, you must use the CreateObject function because the FileSystemObject object is a COM object. Remember that CreateObject takes in the programmatic identifier (ProgID) of the object you want to use. The ProgID for the FileSystemObject object is "Scripting.FileSystemObject", so you use the code
Set fso = CreateObject _ ("Scripting.FileSystemObject")
to create an instance of (i.e., instantiate) that root object.
The FileSystemObject object exposes one property (Drives) and 24 methods. The methods fall into four categories: path manipulation, file and folder operations, text file creation, and objects. Table 3 describes these methods. (Windows 2000—Win2K—will bring additional functionality. For more information, see the sidebar "Windows 2000 Introduces a New Method.")
From the root FileSystemObject object, you can access drives in two ways. You can use the Drives property to access the collection of all the drives currently visible on the local machine. Or you can use the GetDrive method to access a specific drive. Let's look at how you can use the Drives property to enumerate all the drives.
As Listing 1, page 10, shows, you begin the code to enumerate all the drives by declaring the variables. You need to declare the fso variable (a FileSystemObject object), the cDrives variable (a Drives collection object), the drv variable (a Drive object), and the str variable (a string). Next, you instantiate the FileSystemObject object and assign that instance to the fso variable. You then call the Drives property and set the returned collection of drives to cDrives. Using a For Each...Next statement, you loop through each drive in the collection, assigning it to str. Because you're concatenating each drive onto the string, str will contain the entire collection of drives. (The concatenation of the VBScript constant vbCrLf inserts a line return after each drive.) Finally, you use the MsgBox function to display the list of drives.
From the root FileSystemObject object, you can access a folder with the GetFolder method. This method returns a Folder object representing a specific folder. GetFolder's syntax is
where object is the name of a FileSystemObject object and folderspec is the relative or absolute path to a specific folder. An absolute path is a fully qualified path containing drive and directory information before the filename. A relative path is an incomplete path that might not include drive or parent folder information. For example, the path
is an absolute path, whereas the paths
are relative paths. A relative path is relative to the current folder, so the path can refer to different files at different moments in time.
If you want to access Windows, System, or Temp folders, you must use the GetSpecialFolder method instead of GetFolder. GetSpecialFolder's syntax is
where object is the name of a FileSystemObject object and folderspec is a constant. The possible constants are
- WindowsFolder = 0
- SystemFolder = 1
- TemporaryFolder = 2
GetSpecialFolder returns a reference to the special folder you specify.
After you obtain a reference to a Folder object, you can invoke the Folder object's methods and properties. For example, you can use the Copy method to copy the folder or invoke the Path and Type properties to determine the folder's path and type (i.e., the short description that Windows Explorer displays in its Type column). I'll cover the Folder object's properties and methods in detail in a future column.
After you obtain a reference to a Folder object, you can also access the Folder object's collections of files and subfolders. You use the Files property to access the Files collection and the SubFolders property to access the Folders collection. These two collections, in turn, return File and Folder objects, respectively.
If you're unsure of a folder's path, you can query a Folder object. For example, to find out the path for the Windows folder, you can use the code in Listing 2. This code also queries the Folder object for the folder's type.
As Listing 2 shows, you begin the code by declaring the fso variable, the fld variable (a Folder object), and the GetSpecialFolder constants. VBScript doesn't have any predefined mnemonic constants, so you can give the constants the name you want as long as you're consistent with the behavior of GetSpecialFolder (i.e., assign the value of 0 to the Windows folder, 1 to the System folder, and so on). After you instantiate the FileSystemObject object and assign that instance to the fso variable, you use the GetFolder method. Because you don't know the path to the Windows folder, you use the GetSpecialFolder method with the Windows folder constant as the argument. You set the result to the fld variable. Finally, you use the Folder object's Path and Type properties with MsgBox to display the Windows folder's path and type. In this case, the type is File Folder.
From the root FileSystemObject object, you can access a file by using the GetFile method to access a file in a folder. This method's syntax is
where object is the name of a FileSystemObject object and folderspec is the relative or absolute path to a specific file. GetFile returns a File object representing the specified file.
If you don't know the path to a file, you can use the code in Listing 3. As in the previous listings, you begin this code by declaring the variables and constants and instantiating a FileSystemObject object. Next, you use the GetSpecialFolder method to obtain the path to the System folder and assign that path to the windir variable. You then use the BuildPath method to concatenate the path in the windir variable (e.g., C:\windows\system) to the path shell32.dll. BuildPath adds the necessary backslashes, including the required final backslash. After you assign the resulting path to the fileName variable, you can use that variable as the argument to the GetFile method. You set the result to the f variable and use the Path and Type properties with MsgBox to display the shell32.dll file's path and type (in this case, Application Extension).
Using FSO Methods
All the FSO methods in Table 3 are relatively easy to use. On the Microsoft Developer Network (MSDN) Web site, the Scripting Run-Time Reference provides the syntax for the FSO methods and the FileSystemObject Object Tutorial provides examples of how to use them. Alternatively, you can download the VBScript documentation, which includes a couple of chapters and a tutorial about the FSO object model. You can find links to the Scripting Run-Time Reference, the FileSystemObject Object Tutorial, and the VBScript Documentation Download at http://msdn.microsoft.com/scripting/ default.htm?/scripting/vbscript/techinfo/vbsdocs.htm.
Although helpful, the official documentation doesn't give you insights about potential pitfalls that you might encounter while using the FSO methods. Here are two pitfalls that I've run into and how to work around them.
Inaccurate paths. Most of the FSO path manipulation methods don't resolve paths or check paths for existence or consistency. Although the methods are aware of particular path requirements, they treat the paths as raw strings. For example, the code
fileName = fso.BuildPath("C:\dir\", _ "C:\win\") MsgBox fileName
creates the incorrect path C:\dir\C:\win\. BuildPath is smart enough to detect that no additional backslash is necessary between the two elements but not smart enough to realize that the second element also has drive information.
None of the FSO methods let you remove such drive information from a path. However, you can use the user-defined function called StripDriveInfo in Listing 4. This function uses the GetDriveName method to obtain the drive name and assign it to the drv variable. If drv isn't empty (i.e., drv contains drive information), the Mid function extracts the relative path starting from the position that the Len function specifies plus 1. (If you're unfamiliar with Mid, Len, and other string-manipulation functions, see my column "Understanding VBScript: Functions to Manipulate Strings," November 1999.) You add 1 because GetDriveName doesn't include the colon or, in the case of Uniform Naming Convention (UNC) names, the second backslash. With StripDriveInfo, both of these calls
MsgBox StripDriveInfo("C:\dir\win\") MsgBox StripDriveInfo("\\machine\" _& "disk\dir\win\")
return the correct relative path \dir\win\.
No method to obtain folder names. None of the FSO methods let you obtain only a folder name. However, you can use the user-defined function called GetFolderName in Listing 5. This function removes both the drive and file information from a path to obtain the folder name.
To remove the drive information, the GetFolderName function uses the StripDriveInfo function. To remove the file information, you might think that you could use the GetFileName method to obtain the filename to truncate. However, GetFileName works correctly only some of the time. For example, if you use the code
fso.GetFileName _ ("C:\dir\win\myfile.ext")
GetFileName returns the correct filename myfile.ext. However, if you use either of these lines of code
GetFileName returns the filename win, even though that's the correct result for only the latter case. Typically, if a path ends with a backslash, the last element is a folder name, not a filename. But GetFileName reads the last element in a path as a filename, whether or not a backslash follows that element. Thus, if you use GetFileName without any modifications, you might inadvertently truncate the folder name you're trying to obtain.
To avoid this problem, GetFolderName uses the Right function to extract the last character in the relative path that StripDriveInfo returns. If that character is a backslash, GetFolderName sets the fileName variable to an empty string. If that character isn't a backslash, GetFolderName uses the GetFileName method to extract the filename and sets that filename to the fileName variable. If fileName isn't empty, the Mid function extracts only the folder information from the relative path that StripDriveInfo returns. Thus, both of these calls
MsgBox GetFolderName("C:\dir\win\") MsgBox GetFolderName _ ("C:\dir\win\myfile.ext")
return the correct value \dir\win\.
More on FSO to Come
The FSO object model gives you many tools with which to manipulate files and folders. In this column, I've presented an overview of the FSO object model and the main aspects of the FileSystemObject object. Starting next month, I'll discuss in depth the various child objects, such as Drive, File, Folder, and TextStream.