Downloads
129966.zip

A Universal Naming Convention (UNC) path uniquely identifies a resource on a network. It describes the location of a volume, directory, or file, using the format \\server\volume\directory\file. However, most people prefer using a mapped Windows drive letter instead of a UNC path because a mapped drive letter is easier to remember. Therefore, your scripts will likely have to deal with mapped drives and mapped resources from time to time. It's at these times that you'll want to use the WshNetwork and FileSystemObject objects.

The WshNetwork and FileSystemObject objects are a dynamic duo when you need to work with mapped drives in Windows Script Host (WSH) scripts. Besides providing the same capabilities as Windows Management Instrumentation’s (WMI’s) Win32_MappedLogicalDisk class, the WshNetwork object has additional methods for creating and removing drive mappings. The FileSystemObject object provides methods for retrieving information about system drives. With the WshNetwork and FileSystemObject objects, you can easily perform a variety of mapping tasks, as the following examples demonstrate.

 

Determining Whether a Share Is Mapped

The IsDriveMapped function in Listing 1 demonstrates how you can use the WshNetwork object to determine whether a share is mapped. Here’s how this function works. It first uses WshNetwork’s EnumNetworkDrives method to return a list of the mapped network drives on a computer as a collection. This collection contains a pair of items for each mapped network drive: the drive’s local name and its associated UNC path. The collection is zero-indexed so that the even-numbered items in the collection are the drive names and the odd-numbered items are the associated UNC paths. Therefore, the function iterates through every second item in the collection for comparison to the specified share. If there’s a match, the function’s return value is set to true. Otherwise, a value of Nothing is returned, which evaluates to false in Boolean comparisons.

You can download the IsDriveMapped function’s code (and the code in the other listings) by going to the top of this page and click the Download the Code Here button. To use the IsDriveMapped function in a script, you call it using code such as

If IsDriveMapped("\\Svr1\Electronic\") Then

' Do something.

or

If Not IsDriveMapped("W:") Then
' Create a new drive mapping.

Finding the Next Available Drive

Typically, you don't want to map a resource or share to an arbitrary drive letter. It makes more sense to find the next available one. Although the WshNetwork’s object's EnumNetworkDrives method is great for listing mapped drives, it's not much help in finding available drives. A better approach is to use the FileSystemObject's Drives collection, as it contains information about both local and network drives in a system.

The GetNextDrive function in Listing 2 finds the next available drive. The function begins by enumerating the ASCII codes representing the possible drive letters. With this approach, the function’s loop counter can easily convert the ASCII codes into drive letters by applying the Chr() function and appending a colon (:). For example, the ASCII code of 65, which represents the uppercase letter A, is transformed into A:.

GetNextDrive transforms one ASCII code at a time. Once transformed, the function uses the FileSystemObject object’s DriveExists method to determine whether that drive already exists. The DriveExists method returns a value of true when the drive exists and a value of false when it doesn’t exist. If the drive doesn’t exist, the function’s return value is set to that drive letter.

To use the GetNextDrive function, you need to customize the starting and ending loop indexes in the line

Const A_DRIVE = 65, Z_DRIVE = 90

so that they correspond to the available drive letter range in your system. For example, if the A and B drives are reserved for removable devices and the C drive is reserved for the first hard disk partition, you’d change this line to

Const D_DRIVE = 68, Z_DRIVE = 90

so that the function starts from the D drive. You can find a list of the ASCII codes at ASCII Code.

You can use the GetNextDrive function in code such as

strDriveLetter = GetNextDrive()<p class="Code">If Not IsEmpty(strDriveLetter) Then</p><p class="Code">  Set objNetwork = _</p><p class="Code">    WScript.CreateObject("WScript.Network")</p><p class="Code">  objNetwork.MapNetworkDrive _</p><p class="Code">    strDriveLetter, "\\Svr1\Electronic\"</p>

This code uses the GetNextDrive function to find the next available drive, then maps that drive’s letter to the \\Svr1\Electronic\ share. To map the drive, the code uses the WshNetwork object’s MapNetworkDrive method, which I’ll discuss shortly.

 

Disconnecting a Mapped Drive

You can use the WshNetwork object’s RemoveNetworkDrive method to disconnect a mapped drive. This method has one mandatory and two optional arguments:

  • Name. You use this mandatory string argument to specify the name of the mapped drive you want to disconnect. It can be either a local name or a remote name, depending on how the drive is mapped.
  • Force. You use this optional Boolean argument to specify that you want the mapped drive disconnected, even if files are in use. When you specify the value of true, the mapping is removed whether or not the resource is in use. When you don’t include this argument or you specify the value of false, the mapping isn’t removed if the resource is in use.
  • UpdateProfile. You use this optional Boolean argument to specify that you want to remove the mapping from the current user's profile. This argument might be used if the RemoveNetworkDrive method is part of a logon script, for example. When you specify the value of true, the mapping is removed. When you don’t include this argument or you specify the value of false, the mapping isn’t removed.

For example, if you want to remove the Z drive mapping even if a resource is being accessed, you’d use the code

oNetwork.RemoveNetworkDrive("Z:", true)

 

Mapping a Network Drive

You can use the WshNetwork object’s MapNetworkDrive method to map a drive letter to a shared folder or any child folder under a shared folder. MapNetworkDrive has two mandatory and three optional arguments:

  • LocalName. You use this mandatory string argument to specify the drive you want to map. If the name is a drive letter, you need to include the colon (e.g., G:).
  • RemoteName. You use this mandatory string argument to specify the shared folder’s UNC name (e.g., \\ServerName\ShareName, \\ServerName\ShareName\FolderName).
  • UpdateProfile. You use this optional Boolean argument when you want to store the mapping information in the current user's profile. When you specify the value of true, the current user’s profile is updated with the mapping information. When you don’t include this argument or you specify the value of false, the current user’s profile isn’t updated.
  • UserName: You use this optional string argument when you want to map the network drive using the credentials of someone other than the current user.
  • Password: You use this optional string argument to specify the password for the user identified by the UserName argument.

Many times you can map a drive using only the mandatory arguments. In administrative scripts, though, it might be necessary to supply an alternative or elevated set of credentials to successfully connect to a share because you can't map a drive to a folder unless you have permission to access that folder. After the connection is established, the supplied credentials govern access to the network drive for the duration of the connection.

When using the MapNetworkDrive method, it’s important to include some error-handling code because there are a few conditions that can cause it to fail. Common causes are insufficient permissions, the local drive letter is already in use, and a persistent connection (one that reconnects after a reboot or logout). For example, the MapNetworkDrive.vbs script in Listing 3 handles two types of errors: the local drive letter is already in use and a persistent connection already exists. The latter error condition isn’t a fatal one, as you can still disconnect the drive for the current session using RemoveNetworkDrive.

To run MapNetworkDrive.vbs, follow the syntax

MapNetworkDrive.vbs LocalDrive RemoteShare

For example, if you want to map the D drive to the remote share \\Svr1\Electronic\, you’d use the command

MapNetworkDrive.vbs D: \\Svr1\Electronic\

By default, MapNetworkDrive.vbs doesn’t update the current user’s profile with the mapping information. If you want to update the current user’s profile, you can change the line in callout A to

objNetwork.MapNetworkDrive strLocalDrive, _strRemoteShare, True 

Indispensible Tools

The WshNetwork and FileSystemObject objects are indispensable tools when you need to manage mapped drives and resources in WSH scripts. I’ve only covered a few examples of what you can do with them. You can explore other options in MSDN’s WshNetwork Object page and in MSDN’s FileSystemObject Object page.

 

Listing 1: IsDriveMapped Function

Function IsDriveMapped(strShare)Dim oNet, drv, i <p class="Code">  Set oNet = CreateObject("WScript.Network")</p><p class="Code">  Set drv = oNet.EnumNetworkDrives</p><p class="Code">  For i = 0 To drv.Count - 1 Step 2</p><p class="Code">    If StrComp(drv(i + 1), strShare, vbTextCompare) = 0 Then</p><p class="Code">      IsDriveMapped = true</p><p class="Code">      Exit For</p><p class="Code">    End If</p><p class="Code">  Next</p><p class="Code">End Function</p>

Listing 2: GetNextDrive Function

Function GetNextDrive()

Const A_DRIVE = 65, Z_DRIVE = 90 <p class="Code">  Dim FSO, letter, drv</p><p class="Code">  Set FSO = CreateObject("Scripting.FileSystemObject")</p><p class="Code">  For letter = A_DRIVE To Z_DRIVE</p><p class="Code">    drv = Chr(letter) & ":"</p><p class="Code">    If Not FSO.DriveExists(drv) Then</p><p class="Code">      GetNextDrive = drv</p><p class="Code">            Exit Function</p><p class="Code">    End If</p><p class="Code">  Next</p><p class="Code">End Function</p>

Listing 3: MapNetworkDrive.vbs

Dim strLocalDrive, strRemoteShare, objNetwork<p class="Code">strLocalDrive  = UCase(Left(WScript.Arguments.Item(0), 2))</p><p class="Code">strRemoteShare = WScript.Arguments.Item(1)</p><p class="Code">Set objNetwork = CreateObject("WScript.Network")</p><p class="Code">On Error Resume Next </p><p class="Code">objNetwork.MapNetworkDrive strLocalDrive, strRemoteShare, False </p><p class="Code">' Error traps</p><p class="Code">If Err <> 0 Then</p><p class="Code">  Select Case Err.Number</p><p class="Code">  ' Persistent connection so try a second time.</p><p class="Code">    Case -2147023694</p><p class="Code">      Err.Clear</p><p class="Code">      On Error Resume Next</p><p class="Code">      objNetwork.RemoveNetworkDrive strLocalDrive, True, True</p><p class="Code"><strong>' BEGIN CALLOUT A</strong></p><p class="Code">      objNetwork.MapNetworkDrive strLocalDrive, strRemoteShare, False</p><p class="Code"><strong>' END CALLOUT A</strong></p><p class="Code">      WScript.Echo "Second attempt to map drive " & _</p><p class="Code">        strLocalDrive & " to " & strRemoteShare</p><p class="Code">    ' The local drive letter (aka local device name) is already in use.</p><p class="Code">    Case -2147024811</p><p class="Code">      WScript.Echo "ERROR: Failed to map drive " & _</p><p class="Code">        strLocalDrive & " to " & strRemoteShare & ". " & Err.Description</p><p class="Code">    Case Else</p><p class="Code">      WScript.Echo "ERROR: Failed to map drive " & _</p><p class="Code">      strLocalDrive & " to " & strRemoteShare</p><p class="Code">  End Select</p><p class="Code">End If</p>