[Previous] [Table of Contents] [Next]

# Using the Browse For Folder Dialog Box

Handling files and folders interactively requires that the user specify the pathnames of files and folders at run time. In previous chapters, we used the InputBox function or the WSHInputBox method to implement an input dialog box. But how do you implement file dialog boxes in WSH scripts? Let's look at two approaches.

## Using BrowseForFolder to Select Folders

If you need the path to a folder, Windows provides the dialog box shown in Figure 12-17. The user can easily select a drive and the folder. The good news is that you can invoke this dialog box from a WSH script.

Figure 12-17 Dialog box for selecting a folder

> NOTE

> The dialog box is provided by a function contained in the file Shdocvw.dll, which is part of Internet Explorer versions 4 and 5. You also need Shell32.dll version 4.71 or later, which is available in Windows 98 (version 4.72) and Windows 2000 (version 5). In Windows 95 and Windows NT 4, Shell32.dll version 4.71 is available if Internet Explorer 4 is installed with the Active Desktop update. In Windows 95 and Windows NT, installing Internet Explorer 5 doesn't update Shell32.dll. You must install Internet Explorer 4 with Active Desktop and then upgrade to Internet Explorer 5.

Before you can access the methods of the Internet Explorer 4 or 5 Application object, you must create an object reference by using the following command:

    Set objDlg = WScript.CreateObject("Shell.Application")

You can then use the methods of the Application object and its subobjects.

To invoke the dialog box shown in Figure 12-17, you use the BrowseForFolder method:

    Set objF = objDlg.BrowseForFolder(hWnd, Title, Options[, Root])

This method returns a reference to an object of the Windows shell's namespace (which is different from the FileSystemObject object). The parameters of this method are not well documented, but I've collected the following information:

- The first parameter submits a window handle to the dialog box. You should always use the value 0 for this parameter because the script has no handle.

- The second parameter specifies the string shown in the dialog box below the title bar (as shown in Figure 12-17).

- The third parameter is a 32-bit flag that specifies internal features of the dialog box. Table 12-4 shows the constants that can be passed to the method. You can also combine some constants (such as &H0010 and &H0001).

- The fourth parameter is optional and can be used to preselect a folder in the dialog box. You can submit a string with the folder's path (such as C:\Born) or you can use one of the values in Table 12-5 to select a special folder object in the shell's namespace.

Table 12-4 Constants for the Third Parameter of BrowseForFolder*

Constant | Description
--- | ---
&H0001 | Only file system folders can be selected. If this bit is set, the OK button is disabled if the user selects a folder that doesn't belong to the file system (such as the Control Panel folder).
&H0002 | The user is prohibited from browsing below the domain within a network (during a computer search).
&H0004 | Room for status text is provided under the text box. (I haven't found a way to show the status, however.)
&H0008 | Returns file system ancestors only.
&H0010 | Shows an edit box in the dialog box for the user to type the name of an item.
&H0020 | Validate the name typed in the edit box.
&H1000 | Enables the user to browse the network branch of the shell's namespace for computer names.
&H2000 | Enables the user to browse the network branch of the shell's namespace for printer names.
&H4000 | Allows browsing for everything.

* Values are documented in the file Shlobj.h, which is part of the Platform SDK.

Table 12-5 Constants for the Fourth Parameter of BrowseForFolder

Constant | Description
--- | ---
0 | The Desktop (virtual) folder is the root directory. Using this constant along with &H0001 for the third parameter circumvents problems with the OK button.
1 | Internet Explorer is the root.
2 | The Programs folder of the Start menu is the root.
3 | The Control Panel folder is the root. The third parameter must be set to &H4000 (browse for everything).
4 | The Printers folder is the root. The third parameter must be set to &H4000 (browse for everything).
5 | The Documents folder of the Start menu is the root.
6 | The Favorites folder of the Start menu is the root.
7 | The Startup folder of the Start menu is the root. The third parameter must be set to &H4000 (browse for everything).
8 | The Recent folder is the root. The third parameter must be set to &H4000 (browse for everything).
9 | The SendTo folder is the root. The third parameter must be set to &H4000 (browse for everything).
10 | The Recycle Bin folder is the root. The third parameter must be set to &H4000 (browse for everything).
11 | The Start menu folder is the root.
16 | The Desktop (physical) folder is the root.
17 | My Computer is the root.
18 | Network Neighborhood is the root.
19 | The Nethood folder is the root.
20 | The Fonts folder is the root.
21 | The Templates folder is the root.

> NOTE

> The BrowseForFolder method is powerful but potentially dangerous because it can retrieve shell namespace objects. Changing these objects in your script can cause a lot of problems on your machine. If you use the method only to browse file system folders, there's no risk.

The next sample uses only three parameters, and the third parameter is set to &H0010 (show edit box) + &H0001 (only file system objects). If the user selects a folder and closes the dialog box using the OK button, the method returns the selected folder name.

Listing 12-24 invokes a Browse For Folder dialog box. After the user closes the dialog box, the script uses both methods described in this section to detect whether the user clicked the OK button or the Cancel button. Therefore, two dialog boxes with the results are shown. Note that the following sample doesn't return the full path to the selected object. (The next sample has a BrowseForFolder function, which derives the full path to the object.)

Listing 12-24 Dialog.vbs

    '************************************************
    ' File:    Dialog.vbs (WSH sample in VBScript)
    ' Author:  (c) G. Born
    '
    ' Using the shell dialog box to select a folder
    '************************************************
    Option Explicit

    ' Flags for the options parameter
    Const BIF_returnonlyfsdirs   = &H0001
    Const BIF_dontgobelowdomain  = &H0002
    Const BIF_statustext         = &H0004
    Const BIF_returnfsancestors  = &H0008
    Const BIF_editbox            = &H0010
    Const BIF_validate           = &H0020
    Const BIF_browseforcomputer  = &H1000
    Const BIF_browseforprinter   = &H2000
    Const BIF_browseincludefiles = &H4000

    Dim wsh, objDlg, objF

    ' Get Application object of the Windows shell.
    Set objDlg = WScript.CreateObject("Shell.Application")

    ' Use the BrowseForFolder method.
    ' For instance: Set objF = objDlg.BrowseForFolder _
    '     (&H0, "Select the folder to copy", &H10, "C:\Born")

    Set objF = objDlg.BrowseForFolder (&H0, _
        "Select the folder to copy", _
        BIF_editbox + BIF_returnonlyfsdirs)

    ' Here we use the first method to detect the result.
    If IsValue(objF) Then
        MsgBox "Selected folder: " & objF.Title
    Else
        MsgBox "Canceled"
    End If

    ' Here we use TypeName to detect the result.
    If InStr(1, TypeName(objF), "Folder") > 0 Then
        MsgBox "Selected folder: " & objF.Title
    Else
        MsgBox "Canceled"
    End If

    Function IsValue(obj)
        ' Check whether the value has been returned.
        Dim tmp
        On Error Resume Next
        tmp = " " & obj
        If Err <> 0 Then
            IsValue = False
        Else
            IsValue = True
        End If
        On Error GoTo 0
    End Function

    '*** End

> TIP

> The Shdocvw.dll file contains additional objects, properties, and methods for accessing the Windows shell. (See also Chapter 14 for more information on accessing the Windows shell.) You can find descriptions at http://msdn.microsoft.com/library/default.asp. You can also inspect the methods by using the Object Browser in Microsoft Script Editor, Microsoft Visual Basic Editor (which is available in each Microsoft Office application), or Microsoft Visual Basic 5 Control Creation Edition (CCE) if you define a reference to this DLL file. (See Advanced Development with Microsoft Windows Script Host 2.0 for details.)

## Using BrowseForFolder to Select Files

Listing 12-24 doesn't support the path to a given object, and if the user selects a drive, the volume name is retrieved along with the drive letter. The sample also doesn't allow you to select files in the Browse For Folder dialog box.

Let's extend the program a bit. A value of &H4000 (the constant BIF_browseincludefiles) also allows you to use BrowseForFolder to select files. The following command invokes the Browse For Folder dialog box and allows file selection:

    Set oItem = WshShell.BrowseForFolder( _
            &H0, "Select a file or folder to copy", _
            BIF_returnonlyfsdirs + BIF_browseincludefiles, "C:\")

BIF_browseincludefiles must be defined and the variable WshShell must be a valid object variable pointing to the WshShell object. The method returns an object, which is assigned to the variable oItem. This object variable doesn't contain the path to the folder, so you need something to retrieve the full path and the name of a selected object. You can use the following command:

    name = oItem.ParentFolder.ParseName(oItem.Title).Path

Within this statement, the ParentFolder method is applied to the object. This method returns an object that hosts the parent folder. Then you apply the ParseName method to select an entry in the collection. The method retrieves the name of the selected object, which is returned by the oItem.Title property. The Path property of the object contains the entire path, including the name.

At this point, you're done (if you're omitting error checking). Unfortunately, if the user closes the dialog box by clicking the Cancel button, the preceding statement doesn't return a valid path and object name, and a run-time error (code 424) occurs. Also, the BrowseForFolder method causes a run-time error (code 5) in Windows 2000 if a file is selected from the root folder of a drive. In addition, if the user selects a drive, you have to extract the drive letter from the volume name.

To simplify handling, I moved all the code into a user-defined function named BrowseForFolder. You can call the function by using the following statement:

    tmp = BrowseForFolder(Title, flags, dir)

The Title parameter submits the text shown in the dialog box. The flags parameter specifies the code (see Table 12-4) to search for files and folders. The dir parameter is a string containing the path that's selected in the dialog box. If you submit the value "", My Computer is preselected.

The function returns a string containing the path to the object. If the string contains the value "-1", the user clicked the Cancel button. A value of "-5" indicates that the user selected a file in the root folder, which Windows 2000 doesn't allow. You can use the following code to determine whether the returned name is valid:

    file = BrowseForFolder(Title, flags, dir)
    If file = "-5" Then
        WScript.Echo "Not possible to select files in root folder"
    Else
        If file = "-1" Then
            WScript.Echo "No object selected; Cancel clicked"
        Else
            WScript.Echo "Object: ", file
        End If
    End If

Listing 12-25 is a small VBScript program that invokes the Browse For Folder dialog box and lets the user select a file or a folder. The result is shown in a dialog box (Figure 12-18).

Figure 12-18 Selecting a file in the Browse For Folder dialog box

Listing 12-25 FileSelectDialog.vbs

    '********************************************************
    ' File:    FileSelectDialog.vbs (WSH sample in VBScript)
    ' Author:  (c) G. Born
    '
    ' Using the shell dialog box to select a folder
    ' or a file
    ' Warning: A run-time error occurs if the script
    ' is executed in Windows 2000 and the user selects
    ' a file in the root folder of a drive.
    '********************************************************
    Option Explicit

    ' Flags for the options parameter
    Const BIF_returnonlyfsdirs   = &H0001
    Const BIF_dontgobelowdomain  = &H0002
    Const BIF_statustext         = &H0004
    Const BIF_returnfsancestors  = &H0008
    Const BIF_editbox            = &H0010
    Const BIF_validate           = &H0020
    Const BIF_browseforcomputer  = &H1000
    Const BIF_browseforprinter   = &H2000
    Const BIF_browseincludefiles = &H4000

    Dim file

    file = BrowseForFolder( _
            "Select a file or folder to copy", _
            BIF_returnonlyfsdirs + BIF_browseincludefiles, _
            "")
    If file = "-5" Then
        WScript.Echo "Not possible to select files in root folder"
    Else
        If file = "-1" Then
            WScript.Echo "No object selected; Cancel clicked"
        Else
            WScript.Echo "Object: ", file
        End If
    End If

    ' Using the shell's BrowseForFolder method to
    ' return the full path to the selected object
    ' title = Text shown in the dialog box
    ' flag = One of the values for controlling the
    '        BrowseForFolder behavior
    ' dir = Preselected directory (can be "")
    Function BrowseForFolder(title, flag, dir)
        On Error Resume Next

        Dim oShell, oItem, tmp

        ' Create WshShell object.
        Set oShell = WScript.CreateObject("Shell.Application")

        ' Invoke Browse For Folder dialog box.
        Set oItem = oShell.BrowseForFolder(&H0, title, flag, dir)
        If Err.Number <> 0 Then
            If Err.Number = 5 Then
                BrowseForFolder= "-5"
                Err.Clear
                Set oShell = Nothing
                Set oItem = Nothing
                Exit Function
            End If
        End If

        ' Now we try to retrieve the full path.
        BrowseForFolder = oItem.ParentFolder.ParseName(oItem.Title).Path

        ' Handling: Cancel button and selecting a drive
        If Err<> 0 Then
            If Err.Number = 424 Then           ' Handle Cancel button.
                BrowseForFolder = "-1"
            Else
                Err.Clear
                ' Handle situation in which user selects a drive.
                ' Extract drive letter from the title--first search
                ' for a colon (:).
                tmp = InStr(1, oItem.Title, ":")
                If tmp > 0 Then           ' A : is found; use two
                                          ' characters and add \.
                    BrowseForFolder = _
                        Mid(oItem.Title, (tmp - 1), 2) & "\"
                End If
            End If
        End If

        Set oShell = Nothing
        Set oItem = Nothing
        On Error GoTo 0
    End Function

    '*** End

> NOTE

> On machines that had only Windows 2000 or Windows 98 installed, the BrowseForFolder method failed to return valid filenames during the first attempt to access a folder. An error code reported that the selected file was missing. After I installed Microsoft Office on those machines, the error didn't occur again.