Mapping a Drive Letter Programmatically
Some legacy applications do not permit the use of UNC paths when accessing network folders, instead requiring that a drive letter be mapped. When interacting with such software it may be necessary to map a drive letter and later remove mappings using C#.
UNC Paths and Drive Letters
Modern computers are often connected to a network with access to many other remote resources, including shared folders, printers and other devices. These resources are usually referenced with a unique path name defined using the Uniform Naming Convention (UNC). UNC paths generally specify the name of a machine, or cluster of devices, and the name of a folder, file or other resource that is to be accessed. An example of a UNC path that you may use in Windows is "\\BlackWasp\ImageGallery\Wasp.ico". This path leads to the Wasp.ico file, which is held in a shared folder named "ImageGallery" on the "BlackWasp" server.
Earlier in the history of PC operating systems, DOS and Windows-base software relied on the use of drive letters to access files. In the same way that C: usually refers to the main hard disk drive in a PC, other letters would be mapped to networked resources. This permitted applications to open and save files to local and networked folders using the same naming conventions. For example, the "\\BlackWasp\ImageGallery" could be mapped to I:, allowing the file described earlier to be accessed using the path, "I:\Wasp.ico".
The problem with the drive letter approach is that it only permits a maximum of twenty-six local and remote folders to be accessed simultaneously. In a modern office environment this may not be enough. Handily, the use of the UNC is supported by Windows and by the .NET framework without additional effort. However, if you need to interact with older software you may need to add and remove drive letters programmatically.
In this article I will describe some of the manners in which you can map drive letters using C# code. For a demonstration of these methods, download the sample application using the link at the top of this article.
Mapping Drive Letters
The .NET framework does not provide a means of mapping a drive letter. Instead, a Windows API function must be executed using Platform Invocation Services, also known as P/Invoke. To use P/Invoke, classes from the InteropServices namespace are required. To make the code in the samples below more readable, it makes sense to add a using directive for this namespace:
Referencing WNetAddConnection Methods
There are two API functions that can be used to directly map a drive letter to a folder represented by a UNC path. These are called WNetAddConnection2 and WNetAddConnection3. These functions supersede a previous method named WNetAddConnection, which is now present only to allow the correct operation of 16-bit applications.
The two functions are found in the mpr library of the Windows API. We can add references to the functions using the following code:
static extern UInt32 WNetAddConnection2(
ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, uint dwFlags);
static extern UInt32 WNetAddConnection3(
IntPtr hWndOwner, ref NETRESOURCElpNetResource, string lpPassword, string lpUserName,
You can see that the two declarations only differ in one respect. When using WNetAddConnection3, an additional parameter is provided. This parameter, named hWndOwner in the sample above, receives the handle of a window. If the call to the API function results in the display of interactive dialog boxes, the parent window of these dialog boxes will be the one with the specified handle. In all other respects, the two methods are essentially identical.
When selecting between the two functions, use WNetAddConnection2 where there is no visible user interface or where no user interaction will be required. Use WNetAddConnection3 when calling the function from a form within a Windows application.
Defining the NETRESOURCE Structure
The first parameter of WNetAddConnection2, and the second of WNetAddConnection3, accepts a NETRESOURCE structure. This structure contains information relating to the remote resource that you wish to connect to and the drive letter that you want to assign. Before you can use the mapping commands you must declare this structure, ensuring that it exactly matches that expected by the API. To create the structure, add the following:
public struct NETRESOURCE
public uint dwScope;
public uint dwType;
public uint dwDisplayType;
public uint dwUsage;
public string lpLocalName;
public string lpRemoteName;
public string lpComment;
public string lpProvider;
Although the structure defines eight fields, only four of these are required when mapping drive letters. The first, dwType, is used to specify that we want to map to a network folder. This value is always set to a constant value named RESOURCETYPE_DISK. This constant must be defined within the code as follows:
const uint RESOURCETYPE_DISK = 1;
The lpLocalName field holds the drive letter that will be assigned to the mapped path, which is specified in lpRemoteName. The fourth value that must be provided is lpProvider. This string value determines the network provider that will be used to make the connection. However, normally this is set to null to specify that the operating system should automatically determine the provider to use.
21 September 2008