[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:

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

ConstantDescription
&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

ConstantDescription
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).

Click to view at full size.

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.