[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* | Value | Description
--- | --- | ---
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>