vbScript - Browse for Folder or File

Please see my post vbScript - The Basics for more details on vbScript.

Some scripts need input (other than from the command line) from the user. This can be read from the console (StdIn) or from a pop-up textbox (InputBox). This is fine for simple input but you certainly wouldn't want to have to type a folder or file name, especially when it might include a lengthy path. There are several ways to avoid typing a long folder or file name.

If you create a shortcut to your script on the desktop you could drop a folder or file onto the shortcut and access the item via the command line arguments. Each file or folder can be accessed as

Set fso = CreateObject("Scripting.FileSystemObject")

For Each arg in Wscript.Arguments.Unnamed
    Select Case True 
        Case fso.FolderExists(arg): WScript.Echo "Folder:",arg
        Case fso.FileExists(arg)  : WScript.Echo "File:  ",arg
    End Select
Next

But if you want to be able to browse for a file or folder during the execution of the script that is a little trickier. Of files and folders, browsing for folders is easier because the Shell.Application object provides a method for doing that directly. That method is `Shell.BrowseForFolder. The parameters are

  1. a handle (when called from vbScript use the value 0)
  2. text to display in the title bar of the dialog
  3. window options
  4. start folder

Window options can be one or more (add the values) of

Const BIF_RETURNONLYFSDIRS   = &H0001   'Only file system folders can be selected
Const BIF_DONTGOBELOWDOMAIN  = &H0002   'prohibit browsing below the domain within a network
Const BIF_STATUSTEXT         = &H0004   'Room for status text is provided under the text box
Const BIF_RETURNFSANCESTORS  = &H0008   'Returns file system ancestors only
Const BIF_EDITBOX            = &H0010   'Shows an edit box in the dialog box to type a name
Const BIF_VALIDATE           = &H0020   'Validate the name typed in the edit box
Const BIF_BROWSEFORCOMPUTER  = &H1000   'Enables browse the network for computer names
Const BIF_BROWSEFORPRIER     = &H2000   'Enables browse the network for printer names
Const BIF_BROWSEINCLUDEFILES = &H4000   'Allows browsing for everything

start folder can be one of

Const SSF_DESKTOP            = &H0000   'Desktop (virtual) folder
Const SSF_PROGRAMS           = &H0002   'Programs folder of the Start menu
Const SSF_CONTROLS           = &H0003   'Control Panel folder (*)
Const SSF_PRINTERS           = &H0004   'Printers folder (*)
Const SSF_PERSONAL           = &H0005   'Documents folder of the Start menu
Const SSF_FAVORITES          = &H0006   'Favorites folder of the Start menu
Const SSF_STARTUP            = &H0007   'Startup folder of the Start menu (*)
Const SSF_RECENT             = &H0008   'Recent folder (*)
Const SSF_SENDTO             = &H0009   'SendTo folder (*)
Const SSF_BITBUCKET          = &H000a   'Recycle Bin folder (*)
Const SSF_STARTMENU          = &H000b   'User Start menu folder
Const SSF_DESKTOPDIRECTORY   = &H0010   'Desktop (physical) folder
Const SSF_DRIVES             = &H0011   'My Computer
Const SSF_NETWORK            = &H0012   'Network Neighborhood
Const SSF_NETHOOD            = &H0013   'Nethood folder
Const SSF_FONTS              = &H0014   'Fonts folder
Const SSF_TEMPLATES          = &H0015   'Templates folder
Const SSF_COMMONSTARTMENU    = &H0016   'All Users Start Menu
Const SSF_COMMONPROGRAMS     = &H0017   'All Users Programs
Const SSF_COMMONSTARTUP      = &H0018   'All Users Startup
Const SSF_COMMONDESKTOPDIR   = &H0019   'All Users Desktop
Const SSF_APPDATA            = &H001a   'APPDATA (Roaming)
Const SSF_PRINTHOOD          = &H001b   'Printers
Const SSF_LOCALAPPDATA       = &H001c   'APPDATA (local)
Const SSF_WINDOWS            = &H0024   'Windows
Const SSF_SYSTEM             = &H0025   'Windows\System32
Const SSF_PROGRAMFILES       = &H0026   'C:\Program Files
Const SSF_MYPICTURES         = &H0027   'User My Pictures
Const SSF_PROFILE            = &H0028   'User home folder

There are actually more values that can be used than the ones I listed. Try a few and see where they take you. Note that you can also specify a folder directly as in "D:\Temp" in which case the dialog will be restricted to folders in and under that root value. Giving "" as the start folder starts you in This PC.
Browsing for files is a little trickier. You'd thing Microsoft would have provided a Shell.BrowseForFile method, but noooooooooooo.

Windows provides a way to execute HTML in a non-protected environment. Obviously, like any other executable, you should only execute trusted code. Trusted HTML can be run under mshta.exe. Mstha is short for MicroSoft HTml Application. Under mshta.exe you can develop (using any text editor) a fully function GUI application. In this case we will use just the bare functionality. Even if you don't understand how it works (or care) you can still use it as you would any other component.

What we are going to do is create an HTA in a string variable, then execute it and read the output. Our HTA will have a button which will invoke the file browser (it is used to select a file to upload, thus the somewhat confusing title text), then it will resize itself to 0 (hidden) and automatically click the button.

It's not pretty but it does work.

''#region Header                                                                        '
''                                                                                      '
''  Name:                                                                               '
''                                                                                      '
''      Browse.vbs                                                                      '
''                                                                                      '
''  Description:                                                                        '
''                                                                                      '
''      Function to display folder and file selection browse dialogs.                   '
''                                                                                      '
''  Usage:                                                                              '
''                                                                                      '
''      folder = BrowseForFolder (title, options, startPath)                            '
''                                                                                      '
''          title:  dialog title bar text                                               '
''          options:    see ShellConsts.vbs                                             '
''          startPath:  see ShellConsts.vbs                                             '
''                                                                                      '
''          Returns a selected folder or ""                                             '
''                                                                                      '
''      file = BrowseForFile ()                                                         '
''                                                                                      '
''          Returns a selected file of ""                                               '
''                                                                                      '
''  Audit:                                                                              '
''                                                                                      '
''      2018-06-20  rj  Original code                                                   '
''                                                                                      '
''#end region                                                                           '

Function BrowseForFolder (title, options, startPath)

    Dim shell: Set shell = CreateObject("Shell.Application")
    Dim item : Set item  = shell.BrowseForFolder(0, title, options, startPath)

    'If Cancel or Close is clicked, or no selection is made then the result is Nothing

    If item is Nothing Then
        BrowseForFolder = ""
    Else
        BrowseForFolder = item.Items().Item.Path
    End If
    
End Function

Function BrowseForFile()

    Dim wso: Set wso = CreateObject("Wscript.Shell")
    Dim hta: hta = """about:<input type=file id=file>"                          & vbcrlf _
                 & "<script>resizeTo(0,0);"                                     & vbCrLf _
                 & "   file.click();"                                           & VbCrLf _
                 & "   fso = new ActiveXObject('Scripting.FileSystemObject');"  & vbCrLf _
                 & "   fso.GetStandardStream(1).WriteLine(file.value);"         & vbCrLf _
                 & "   close();"                                                & VbCrLf _
                 & "</script>"""

    BrowseForFile = wso.Exec("mshta.exe " & hta).StdOut.ReadLine

End Function

''Test code                                                                             '
If StrComp(Wscript.ScriptName,"Browse.vbs") = 0 Then
    WScript.Echo "Folder=" & BrowseForFolder("Browse for folder",0,"")
    WScript.Echo "File  =" & BrowseForFile()
End If