[Previous] [Table of Contents] [Next]

Accessing Drives

The FileSystemObject object provides a way to access all drives known on your machine (all drives that can be accessed from Windows, including floppy disk drives, CD-ROM drives, hard disks, and network drives that are mapped to logical drive letters).

Listing All Drives on a Machine

Let's use FileSystemObject in a WSH script to display the drive letters, drive types, and label names of all drives known on a machine. Drives that support removable media must be checked for whether a medium (such as a CD or floppy disk) is in the drive. If a network drive is found, the script displays the UNC network path. The dialog box in Figure 12-1 lists the drives on one of my test systems.

Figure 12-1 A list of drives on a machine

NOTE
Some of the drives shown in Figure 12-1 (such as drive F) are listed without a label name because I didn't assign a label to these drives. The drives A and G are listed without a label because a floppy disk or CD wasn't inserted in the drive.

To list all drives available in the system, you need an instance of the FileSystemObject object as well as a reference to the Drives object. You create the FileSystemObject object instance as follows:

Set fso = WScript.CreateObject("Scripting.FileSystemObject")

Then you use the object variable fso to read the Drives property, which returns a collection of Drive objects. The following statement retrieves the Drives collection, which contains all drives found on the local machine:

Set oDrive = fso.Drives

You can use a simple loop to access the drives in the collection:

For Each i In oDrive
    
Next

The object variable i receives one drive object on each pass, so you can use this variable within the loop to access the properties of a drive. For example, to retrieve the drive letter, you can use the following statement:

driveletter = i.DriveLetter

To get the drive type, you use the DriveType property of the object referenced in the object variable i:

Type = i.DriveType

The drive type is coded as an integer value in the range between 0 and n. Table 12-2 lists the codes for valid drive types.

Table 12-2 Drive Types

Constant*ValueDescription
Unknown 0 Unknown drive type. (Drive type couldn't be detected.)
Removable 1 A drive with removable media (such as a floppy disk drive or a ZIP drive).
Fixed 2 A fixed disk. This type includes removable hard disks.
Remote 3 Network drive. Indicated only for mapped resources (shared drives and folders).
CDROM 4 CD-ROM drive. There's no difference between CD-R and CD-RW.
RAMDisk 5 A RAM drive. A RAM disk is created within memory using a special driver.

* The Constant column lists the constant names used for the drive types in the Scrrun.dll type library. The Value column lists the values returned in the DriveType property. VBScript and JScript don't support the constants defined in the type library, so you must define these named constants explicitly in your .vbs and .js script files. In WSH 2, you can use the <reference> element in a .wsf file to create a reference to a type library. I'll show you an example of this shortly.

You can use the VolumeName property to retrieve the label (also called the volume name) that's assigned to a medium when it's formatted. If the drive type supports removable media, the medium must be inserted in the drive for you to retrieve the volume name. If the drive contains no medium, it makes no sense to retrieve the VolumeName property. However, you can use the IsReady property to check whether the medium is available. If it is, IsReady returns the value True.

For mapped network drives, the drive name contains no information about the real resource name because the user assigns the associated drive letter manually. You can, however, use the ShareName property of the drive (object) to determine the UNC path to the resource.

The program in Listing 12-1 lists all drives found on a machine. (This sample, like the others in this chapter, is in the \WSHDevGuide\Chapter12 folder on the book's companion CD.)

Listing 12-1 ListDrives.vbs

'**************************************************
' File:    ListDrives.vbs (WSH sample in VBScript) 
' Author:  (c) G. Born
'
' Listing the drives of a machine by using
' FileSystemObject
'**************************************************
Option Explicit

' Drive type constants
Const Unknown = 0 
Const Removable = 1  ' Removable medium
Const Fixed = 2      ' Fixed medium (hard disk)
Const Remote = 3     ' Network drive
Const CDROM = 4      ' CD-ROM
Const RAMDisk = 5    ' RAM disk

Dim Text, Title
Dim fso, oDrive, curDrive    ' Object variables

Dim drtype(6)
drtype(0) = " Unknown "
drtype(1) = " Removable "
drtype(2) = " Fixed "
drtype(3) = " Remote "
drtype(4) = " CDROM "
drtype(5) = " RAMDisk "

Text = "Drives" & vbCrLf & vbCrLf
Title = "WSH sample - by G. Born"

' Create FileSystemObject object to access the file system.
Set fso = WScript.CreateObject("Scripting.FileSystemObject")

Set oDrive = fso.Drives    ' Get Drives collection.

For Each curDrive In oDrive       ' All drive objects
    Text = Text & curDrive.DriveLetter & vbTab  ' Drive letter
    Text = Text & drtype(curDrive.DriveType)
    Select Case curDrive.DriveType      ' Identify drive type.
        Case Removable                  ' Removable medium
            If curDrive.IsReady Then
                Text = Text & curDrive.VolumeName ' Local drive
            End If    

        Case CDROM                      ' CD-ROM
            If curDrive.IsReady Then
                Text = Text & curDrive.VolumeName ' Local drive
            End If    

        Case Remote 
            Text = Text & curDrive.ShareName  ' Network drive

        Case Else                       ' Other medium
            Text = Text & curDrive.VolumeName  ' Local drive
    End Select
    Text = Text & vbCrLf
Next

MsgBox Text, vbOKOnly + vbInformation, Title

'*** End

TIP
In VBScript, the vbTab named constant inserts a tab character into a string so that the output in the dialog box is formatted in columns.

The JScript implementation

In JScript, you also use the FileSystemObject object to list all drives. The following statements create a FileSystemObject object and a Drives collection:

var fso = new ActiveXObject("Scripting.FileSystemObject");
var oDrives = new Enumerator(fso.Drives);  // Get Drives collection.

The native new ActiveXObject statement creates the object instance. The second line contains the JScript keyword Enumerator, which creates a new object variable that contains the Drives collection. After retrieving this collection, you can use the atEnd and moveNext methods of the Enumerator object to access all items in the collection using a for loop. You can get the object from the item property by using this statement:

oDrive.item();

The loop shown here accesses all items in the collection:

for (; !oDrives.atEnd(); oDrives.moveNext())
{
    var drive = oDrive.item();   // Fetch object.
    
}

You can then use properties of the Drive object, such as DriveLetter, DriveType, ShareName, and VolumeName. To avoid defining the drive type constants explicitly within the script, you can add a reference to the type library by adding the following <reference> definition to the .wsf file:

<reference guid='{420B2830-E718-11CF-893D-00A0C9054228}'/>

The reference above uses the guid value of the FileSystemObject object. Listing 12-2 shows the full JScript implementation using a .wsf file.

Listing 12-2 ListDrives.wsf

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- 
    File:    ListDrives.wsf (WSH 2)
    Author:  (c) G. Born
    Listing the drives of a machine
-->

<job id="ListDrives">
    <reference guid='{420B2830-E718-11CF-893D-00A0C9054228}'/>

    <script language="JScript">
    <![CDATA[
        // List all drives on a machine. The drive type values are
        // obtained from the FileSystemObject type library.

        var drtype = new Array(5);

        drtype[0] = " Unknown ";
        drtype[1] = " Removable ";
        drtype[2] = " Fixed ";
        drtype[3] = " Remote ";
        drtype[4] = " CDROM ";
        drtype[5] = " RAMDisk ";

        Text = "Drives \n\n";
        Title = "WSH sample - by G. Born";

        // Create FileSystemObject object to access the file system.
        // Here we use the native method provided by JScript.
        var fso = new ActiveXObject("Scripting.FileSystemObject");

        // Get drives enumerator.
        var oDrive = new Enumerator(fso.Drives);  

        for (; !oDrive.atEnd(); oDrive.moveNext())  
        {
            var drive = oDrive.item();                // Fetch object.
            Text = Text + drive.DriveLetter + " \t "; // Drive letter
            Text = Text + drtype[drive.DriveType];

            if (drive.DriveType == Remote)  
                Text = Text + drive.ShareName;        // Network drive
 
            if ((drive.DriveType == Removable) ||    
                (drive.DriveType == CDROM))        // Removable medium
                if (drive.IsReady) 
                    Text = Text + drive.VolumeName;   // Local drive
  
            if (drive.DriveType == Fixed)  
                Text = Text + drive.VolumeName;       // Local drive

            Text = Text + "\n";
        }

        // Show result.
        var objAdr = WScript.CreateObject("WScript.Shell");
        objAdr.Popup(Text, 0, Title);
    ]]>
    </script>
</job>

TIP
In JScript, the escape character \t inserts a tab character into a string so that the output in the dialog box is formatted in columns. The JScript implementation, ListDrives.js, is also on the companion CD.

Showing Drive Properties

Now let's write a script to query the user for a drive letter via an input dialog box (Figure 12-2). After the user enters a valid drive letter (without the colon), the script retrieves the drive's properties (such as the file system, the free space, and so on) and shows them in a second dialog box (Figure 12-3).

Figure 12-2 Querying the user for a drive letter

Figure 12-3 Drive properties

This sample shows the necessary tests that you must make in a script before you can access a drive. If you omit these tests, a run-time error will probably occur.

The following statement queries for the drive letter using the VBScript InputBox function:

drive = InputBox("Drive letter (e.g. A)", "Drive", "C")

NOTE
The script uses the statement drive = Left(drive, 1) to extract the first character (the drive letter) the user enters.

After you retrieve the user input, it makes sense to check whether the drive letter is valid. For example, the drive "0" doesn't make sense. You can use an If statement such as the following to check the user input:

If Asc(UCase(drive)) < Asc("A") Or _
   Asc(UCase(drive)) > Asc("Z") Then …

If a valid drive letter between A and Z is detected, the script must create a reference to the FileSystemObject object:

Set fso = WScript.CreateObject("Scripting.FileSystemObject")

Before you can access the drive's properties, you must check whether the drive exists. You can do this by using the DriveExists method:

If (Not fso.DriveExists(drive)) Then
    WScript.Echo "The drive " & drive & " doesn't exist"
    WScript.Quit
End If

Only if the method returns the value True can you access the drive from the script. In this case, you can create a Drive object by using the following statement:

Set oDrive = fso.GetDrive(drive)

The GetDrive method returns an object, so you must use the Set keyword in the assignment statement. (Otherwise, the script causes a run-time error.) Before you can access the object's properties, you must check whether the drive is ready. If you omit this check, each attempt to access a drive that doesn't contain a medium will cause a run-time error. You can use the following statement to perform the check:

If (drive.IsReady) Then
    
End If

The IsReady property returns the value True if the drive contains a medium and is ready.

TIP
The sample code doesn't differentiate between drive types when checking IsReady, which means that IsReady is sometimes checked unnecessarily. For example, the IsReady property always returns True on a (formatted) hard disk. Of course, checking IsReady on hard disks doesn't do any harm, and after this one check, you can access the media/drive properties freely, regardless of the drive type.

Another interesting property is TotalSize, which returns the medium capacity, as shown here:

WScript.Echo "Capacity: " & _
             FormatNumber(oDrive.TotalSize/(1024*1024), 0) & _
             " MB" & vbCrLf

This statement uses the VBScript function FormatNumber to format the result using a separator for thousands. By dividing the result by 1024 * 1024, you get the capacity in megabytes. To retrieve the free drive capacity, use this statement:

WScript.Echo "Free: " & FormatNumber(oDrive.FreeSpace/1024, 0) & _
             " KB" & vbCrLf

The full VBScript program is shown in Listing 12-3. It uses a .wsf file to allow references to the type library. The pure VBScript solution is in the file GetDriveX.vbs.

NOTE
You can use the FreeSpace and AvailableSpace properties to retrieve the free space on a medium. Both properties return the same value unless the operating system (such as Windows 2000) supports quotas. Then the administrator can set a space quota for each user on the medium. In such cases, the FreeSpace property specifies the free space for the volume (the entire disk), and the AvailableSpace property specifies the free space for the current user. Because of bugs in Windows 95 OSR 2, problems occur with the FreeSpace and AvailableSpace properties on that platform if the drive is bigger than 2 GB. Wrong values for the capacity are returned.

Listing 12-3 GetDriveX.wsf

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- 
    File:    GetDriveX.wsf (WSH 2)
    Author:  (c) G. Born
    Showing the properties of a drive by using 
    FileSystemObject and a reference to the type library
-->

<job id="GetDriveX">
    <reference guid='{420B2830-E718-11CF-893D-00A0C9054228}'/>

    <script language="VBScript">
    <![CDATA[
        Option Explicit

        Dim Text, Title, drive
        Dim fso, oDrive                 ' Object variable

        Dim drtype(6)
        drtype(0) = " Unknown "
        drtype(1) = " Removable "
        drtype(2) = " Fixed "
        drtype(3) = " Remote "
        drtype(4) = " CDROM "
        drtype(5) = " RAMDisk "

        Text = "Drive" & vbCrLf & vbCrLf
        Title = "WSH sample - by G. Born"

        drive = ""
        Do                      ' Query drive letter.
            drive = InputBox("Drive letter (e.g. A)", "Drive", "C")

            If drive = "" Then  ' Test for Cancel button.
                WScript.Quit
            End If

            drive = Left(drive, 1)  ' Extract drive letter. 
    
            ' Valid drive name (between A and Z)?
            If Asc(UCase(drive)) < Asc("A") Or _
               Asc(UCase(drive)) > Asc("Z") Then 
                MsgBox "Drive " & drive & " is illegal"
                drive = ""
            End If
        Loop Until drive <> ""

        ' Create FileSystemObject object to access the file system.
        Set fso = WScript.CreateObject("Scripting.FileSystemObject")

        ' Check whether drive exists.
        If (Not fso.DriveExists(drive)) Then
            WScript.Echo "The drive " & drive & " doesn't exist"
            WScript.Quit
        End If

        Set oDrive = fso.GetDrive(drive)    ' Get Drive object.

        If (oDrive.IsReady) Then
            Text = Text & UCase(drive) & " - " & _
                   oDrive.VolumeName & vbCrLf
            Text = Text & "Drive type: " & _
                   drtype(oDrive.DriveType) & vbCrLf
            Text = Text & "File system: " & _
                   oDrive.FileSystem & vbCrLf
            Text = Text & "Capacity: " & _
                   FormatNumber(oDrive.TotalSize/(1024*1024), 0) & _
                   " MB" & vbCrLf
            Text = Text & "Free: " & _
                   FormatNumber(oDrive.FreeSpace/1024, 0) & _
                   " KB" & vbCrLf
        Else
            Text = Text & "Drive not ready" & vbCrLf
        End If

        MsgBox Text, vbOKOnly + vbInformation, Title
    ]]>
    </script>
</job>

The JScript implementation

The JScript version uses the same methods and properties. You must replace a few functions with their JScript counterparts, however. For example, the JScript version uses WSHInputBox (a VBScript function introduced in Chapter 8) to implement a user input dialog box. Also, to convert lowercase characters to uppercase, you must apply the JScript toUpperCase method to a String object instead of using the VBScript UCase function. In addition, the format function used in the VBScript sample isn't available in JScript, so I have added a small VBScript function, JsFormatNumber, that provides the missing functionality. The full JScript implementation (as a .wsf file) is shown in Listing 12-4.

Listing 12-4 GetDriveXJS.wsf

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- 
    File:    GetDriveXJS.wsf (WSH 2)
    Author:  (c) G. Born
    Showing the properties of a drive by using 
    FileSystemObject and a reference to the type library
    and using a VBScript function to obtain user input
-->

<job id="ListDrives">
    <reference guid='{420B2830-E718-11CF-893D-00A0C9054228}'/>

    <script language="VBScript">
    <![CDATA[
        Function WSHInputBox(Message, Title, Value)
            ' Provides an InputBox function for JScript
            ' It can be called from JScript as follows:
            ' var result = WSHInputBox("Enter a name","Input",test);
            WSHInputBox = InputBox(Message, Title, Value)
        End Function
    ]]>
    </script>

    <script language="VBScript">
    <![CDATA[
        Function JsFormatNumber (value, decimals)
            ' Formats a number 
            JsFormatNumber = FormatNumber(value, decimals)
        End Function
    ]]>
    </script>

    <script language="JScript">
    <![CDATA[
        // JScript part to retrieve and show drive properties
        // Define an array with drive type text constants.
        var drivetype = new Array(" Unknown ", " Removable ",
                                  " Fixed ", " Remote ", 
                                  " CDROM ", " RAMDisk ");

        var Text = "Drive\n\n";
        var Title = "WSH sample - by G. Born";

        // Query drive letter.
        var drive = WSHInputBox("Drive letter (e.g. A)",
                                "Drive", "C");

        if (drive == "")   // Test for Cancel button.
            WScript.Quit();

        drive = drive.substr(0, 1);  // Extract drive letter.

        // Create FileSystemObject object to access the file system.
        var fso = new ActiveXObject("Scripting.FileSystemObject");

        // Check whether drive exists.
        if (!fso.DriveExists(drive))
        {
            WScript.Echo("The drive " + drive + " doesn't exist");
            WScript.Quit();
        }

        var oDrive = fso.GetDrive(drive);      // Get drive object.

        if (oDrive.IsReady)
        {
            Text = Text + drive.toUpperCase() + ": "  + 
                   oDrive.VolumeName + "\n";
            Text = Text + "Drive type: " + 
                   drivetype[oDrive.DriveType] + "\n";
            Text = Text + "File system: " + oDrive.FileSystem + "\n";
            Text = Text + "Capacity: " + 
                   JsFormatNumber(oDrive.TotalSize/1024/1024, 0) + 
                   " MB\n";
            Text = Text + "Free: " + 
                   JsFormatNumber(oDrive.FreeSpace/1024, 0) + " KB\n";
        }
        else
            Text = Text + "Drive not ready\n";

        var objAdr = WScript.CreateObject("WScript.Shell");
        objAdr.Popup(Text, 0, Title);
    ]]>
    </script>
</job>