VB.NET – Map network drive

May 30, 2010 — 21 Comments

There is no .NET method for creating a network drive yet (as of .NET 4.0) so here is how you can do it using good old Windows APIs 🙂 As well as the API definitions, I’ve included a managed method that wraps up the functionality of the API so that it is easier to use from .NET code.

Here are the API definitions:

Public Const NO_ERROR As UInteger = 0
Public Const RESOURCETYPE_DISK As UInteger = 1

”’ <summary>
”’ Contains information about a network resource. Used by the WNetAddConnection2 method
”’ </summary>
<StructLayoutAttribute(LayoutKind.Sequential)> _
Public Structure NETRESOURCE
Public dwScope As UInteger
Public dwType As UInteger
Public dwDisplayType As UInteger
Public dwUsage As UInteger
<MarshalAsAttribute(UnmanagedType.LPWStr)> _
Public lpLocalName As String
<MarshalAsAttribute(UnmanagedType.LPWStr)> _
Public lpRemoteName As String
<MarshalAsAttribute(UnmanagedType.LPWStr)> _
Public lpComment As String
<MarshalAsAttribute(UnmanagedType.LPWStr)> _
Public lpProvider As String
End Structure

”’ <summary>
”’ Creates a connection to a network resource
”’ </summary>
”’ <param name=”lpNetResource”>A NETRESOURCE structure that specifies information about the network resource connection</param>
”’ <param name=”lpPassword”>The password to use for the connection – leave blank to use current user credentials</param>
”’ <param name=”lpUserName”>The username to use for the connection – leave blank to use current user credentials</param>
”’ <param name=”dwFlags”>Bitmask that specifies connection options. For example, whether or not to make the connection persistent</param>
<DllImportAttribute(“mpr.dll”, EntryPoint:=“WNetAddConnection2W”)> _
Public Shared Function WNetAddConnection2(ByRef lpNetResource As NETRESOURCE, <InAttribute(), MarshalAsAttribute(UnmanagedType.LPWStr)> ByVal lpPassword As String, <InAttribute(), MarshalAsAttribute(UnmanagedType.LPWStr)> ByVal lpUserName As String, ByVal dwFlags As UInteger) As UInteger
End Function

and here is my .NET method that makes the API easier to use – the idea is that you call this .NET method and just pass in basic information instead of having to call the API directly and mess around building structures etc each time:

”’ <summary>
”’ Creates a network drive (aka mapped drive) using the specified drive letter, UNC path and optional credentials
”’ </summary>
”’ <param name=”UncPath”>The UNC path (\\servername\share) to map the drive letter to</param>
”’ <param name=”DriveLetter”>The drive letter to use</param>
”’ <param name=”Persistent”>False to have this drive removed when the user logs off. True to have the drive remembered.
”’ This option is the equivelant of the Reconnect At Logon checkbox shown when mapping a drive in Windows Exporer</param>
”’ <param name=”ConnectionUsername”>The username to use for the connection – optional</param>
”’ <param name=”ConnectionPassword”>The password to use for the connection – optional</param>
Public Shared Sub MapNetworkDrive(ByVal UncPath As String, ByVal DriveLetter As Char, ByVal Persistent As Boolean, Optional ByVal ConnectionUsername As String = Nothing, Optional ByVal ConnectionPassword As String = Nothing)
If String.IsNullOrEmpty(UncPath) Then
Throw New ArgumentException(“No UNC path specified”, “UncPath”)
End If
Dim DriveInfo As New NETRESOURCE
With DriveInfo
.dwType = RESOURCETYPE_DISK
.lpLocalName = DriveLetter & “:”
.lpRemoteName = UncPath
End With
Dim flags As UInteger = 0
If Persistent Then
flags = &H1
End If
Dim Result As UInteger = WNetAddConnection2(DriveInfo, ConnectionPassword, ConnectionUsername, flags)
If Not Result = NO_ERROR Then
Throw New System.ComponentModel.Win32Exception(CInt(Result))
End If
End Sub

So now you can just call my MapNetworkDrive method like so whenever you want to map a drive:

‘Map the F drive to \\MyServer\SomeShareName and
‘make it persistent (reconnect at logon)
MapNetworkDrive(“\\MyServer\SomeShareName”, “F”c, True)
‘Of course you should add some error handling too

I’ll make another blog post soon on how to delete existing mapped drives as well.

21 responses to VB.NET – Map network drive

  1. 

    Wow, I have been trying to get other peoples code for this to work for days. Yours works like a charm.

    Thanks a bunch.

  2. 

    Works like a charm. WooHoo. okay, now how do I disconnect the mapping? I need to be able to enter different servers and retrieve data from some text files. Thanks.

    • 

      This is the source code from the RemoveNetworkDrive method in my Windows API class library (which you can download from this blog), hope it helps:

      ”’

      ”’ Deletes an existing mapped network drive
      ”’

      ”’ The drive letter to delete, must be a network drive
      ”’ Force the drive to be deleted even if files are still open on this drive
      Public Shared Sub RemoveNetworkDrive(ByVal DriveLetter As Char, ByVal Force As Boolean)
      Dim Result As UInteger = ApiDefinitions.WNetCancelConnection(DriveLetter & “:”, ApiDefinitions.CONNECT_UPDATE_PROFILE, Force)
      If Not Result = ApiDefinitions.NO_ERROR Then
      Throw New System.ComponentModel.Win32Exception(CInt(Result))
      End If
      End Sub

    • 

      Oh and if you are just programmatically accessing shares on servers to get at some files and thats it then you should just access the files via the UNC path (the path that you map the network drive to) rather than bothering with mapping and unmapping a network drive

  3. 

    Actually, while trying to figure out the disconnect I came across this. Seems cleaner.

    Public Declare Function WNetAddConnection2 Lib “mpr.dll” Alias “WNetAddConnection2A” _
    ( ByRef lpNetResource As NETRESOURCE, ByVal lpPassword As String, _
    ByVal lpUserName As String, ByVal dwFlags As Integer) As Integer

    Public Declare Function WNetCancelConnection2 Lib “mpr” Alias “WNetCancelConnection2A” _
    (ByVal lpName As String, ByVal dwFlags As Integer, ByVal fForce As Integer) As Integer

    _
    Public Structure NETRESOURCE
    Public dwScope As Integer
    Public dwType As Integer
    Public dwDisplayType As Integer
    Public dwUsage As Integer
    Public lpLocalName As String
    Public lpRemoteName As String
    Public lpComment As String
    Public lpProvider As String
    End Structure

    Public Const ForceDisconnect As Integer = 1
    Public Const RESOURCETYPE_DISK As Long = &H1

    Public Function MapDrive(ByVal DriveLetter As String, ByVal UNCPath As String) As Boolean

    Dim nr As NETRESOURCE
    Dim strUsername As String
    Dim strPassword As String

    nr = New NETRESOURCE
    nr.lpRemoteName = UNCPath
    nr.lpLocalName = DriveLetter & “:”
    strUsername = Nothing ‘(add parameters to pass this if necessary)
    strPassword = Nothing ‘(add parameters to pass this if necessary)
    nr.dwType = RESOURCETYPE_DISK

    Dim result As Integer
    result = WNetAddConnection2(nr, strPassword, strUsername, 0)

    If result = 0 Then
    Return True
    Else
    Return False
    End If
    End Function

    Public Function UnMapDrive(ByVal DriveLetter As String) As Boolean
    Dim rc As Integer
    rc = WNetCancelConnection2(DriveLetter & “:”, 0, ForceDisconnect)

    If rc = 0 Then
    Return True
    Else
    Return False
    End If

    End Function

  4. 

    i have an application that loads as a service. can/will your code function in that scenario? i know there are a lot of issues around the credentials especially when crossing domain and server to server.
    You added a comment above regarding just using UNC versus mapping a drive letter… how would that be done (is the variable value optional)?

  5. 

    I am running Windows 7. The code you have documented here runs without a error. However, the network share does not appear in ‘My Computer’ nor is it visible via the CMD prompt using ‘net use’

    Any ideas?

    BTW, Many thanks for publishing this code.

    • 

      Do you get the same issue if you tell it to be persistent (pass in True for the last parameter) or does it appear when you do that?

      • 

        Same here, it is weird because in my IDE (VS2010) it works fine in testing, but the moment I deploy the code it doesn’t work as expected (also, I am integrating this in an aspx page on a webserver in my company’s domain) Any ideas?

      • 

        Sorry I have no idea about web development. If it was a desktop app and running on Vista/Windows 7 then I would say its probably a UAC issue (mapped drives don’t seem to carry over into your normal logon session if mapped from an app running “As Administrator”) but no idea how this works in a web environment I’m afraid

  6. 

    The app I am using your code in is run with ‘admin’ rights. Afthough the function passes back true, I do not see the drives mapped in my computer OR using net use from the cmmand prompt.

    However, when I run as a normal user (not ‘run as admin’) the shares appear as expected. Wierd.

    • 

      When you do Run As Admin do you have to enter an admin user’s credentials or do you just have to click Yes on the UAC prompt?

      • 

        Program A is an app used to change the IP address of the ethernet adapter. So it needs to be run as admin just click yes at UAC prompt. I want to add the ability to map shares from this app too. However when run as admin the shares do not appear in ‘my computer’. After doing some reading it is because of the LUID. I am not aware of a way to start a 2nd process with lower priviledges in order to work around this problem.

        Try running you app and admin and then mapping a share. It doesn’t work.

  7. 

    Hi,

    Does this check to see if there is already a mapping in place and if not any idea’s how we check?

    Kind regards

    Mike

  8. 

    Thanks for the awesome code!

    For the vista/win7/win8 issue of different shares for the standard vs elevated user you can add this registry key to make any shares added apply to both. After adding the key you’ll need to disconnect and reconnect the drive to see an effect.

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
    “EnableLinkedConnections”=dword:00000001

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s