Results 1 to 13 of 13

Thread: Mapping a network drive

  1. #1

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Mapping a network drive

    Unfortunately in the .NET Framework there is currently no way to create a network drive (aka mapped drive) so we have to use a Windows API to accomplish this, the WNetAddConnection2 API to be precise. So I thought I would provide the VB.NET definitions for the API function and the relevant structures/constants, along with a .NET method that you can use to wrap this API functionality to make it easier to use

    EDIT: The .NET wrapper for this function and loads of others are all in my .NET Windows API Library which you can download here to save copying and pasting API definitions etc into your projects: http://cjwdev.wordpress.com/2011/06/...-2-2-released/

    First of all make sure you use this at the very top of your code:
    vb Code:
    1. Imports System.Runtime.InteropServices
    then you can copy and paste these API definitions, which I've added comments to just in case you do want to use these directly instead of using the .NET method I will provide later in this post.
    vb Code:
    1. 'Constants
    2.     Public Const NO_ERROR As UInteger = 0
    3.     Public Const RESOURCETYPE_DISK As UInteger = 1
    4.  
    5.     ''' <summary>
    6.     ''' Creates a connection to a network resource
    7.     ''' </summary>
    8.     ''' <param name="lpNetResource">A NETRESOURCE structure that specifies information about the network resource connection</param>
    9.     ''' <param name="lpPassword">The password to use for the connection - leave blank to use current user credentials</param>
    10.     ''' <param name="lpUserName">The username to use for the connection - leave blank to use current user credentials</param>
    11.     ''' <param name="dwFlags">Bitmask that specifies connection options. For example, whether or not to make the connection persistent</param>
    12.     <DllImportAttribute("mpr.dll", EntryPoint:="WNetAddConnection2W")> _
    13.     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
    14.     End Function
    15.  
    16.     ''' <summary>
    17.     ''' Contains information about a network resource. Used by the WNetAddConnection2 method
    18.     ''' </summary>
    19.     <StructLayoutAttribute(LayoutKind.Sequential)> _
    20.     Public Structure NETRESOURCE
    21.         Public dwScope As UInteger
    22.         Public dwType As UInteger
    23.         Public dwDisplayType As UInteger
    24.         Public dwUsage As UInteger
    25.         <MarshalAsAttribute(UnmanagedType.LPWStr)> _
    26.         Public lpLocalName As String
    27.         <MarshalAsAttribute(UnmanagedType.LPWStr)> _
    28.         Public lpRemoteName As String
    29.         <MarshalAsAttribute(UnmanagedType.LPWStr)> _
    30.         Public lpComment As String
    31.         <MarshalAsAttribute(UnmanagedType.LPWStr)> _
    32.         Public lpProvider As String
    33.     End Structure

    and here is the .NET method I wrote that makes using the API much simpler:

    vb Code:
    1. ''' <summary>
    2.     ''' Creates a network drive (aka mapped drive) using the specified drive letter, UNC path and optional credentials
    3.     ''' </summary>
    4.     ''' <param name="UncPath">The UNC path (\\servername\share) to map the drive letter to</param>
    5.     ''' <param name="DriveLetter">The drive letter to use</param>
    6.     ''' <param name="Persistent">False to have this drive removed when the user logs off. True to have the drive remembered.
    7.     ''' This option is the equivelant of the Reconnect At Logon checkbox shown when mapping a drive in Windows Exporer</param>
    8.     ''' <param name="ConnectionUsername">The username to use for the connection - optional</param>
    9.     ''' <param name="ConnectionPassword">The password to use for the connection - optional</param>
    10.     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)
    11.         If String.IsNullOrEmpty(UncPath) Then
    12.             Throw New ArgumentException("No UNC path specified", "UncPath")
    13.         End If
    14.         Dim DriveInfo As New NETRESOURCE
    15.         With DriveInfo
    16.             .dwType = RESOURCETYPE_DISK
    17.             .lpLocalName = DriveLetter & ":"
    18.             .lpRemoteName = UncPath
    19.         End With
    20.         Dim flags As UInteger = 0
    21.         If Persistent Then
    22.             flags = &H1
    23.         End If
    24.         Dim Result As UInteger = WNetAddConnection2(DriveInfo, ConnectionPassword, ConnectionUsername, flags)
    25.         If Not Result = NO_ERROR Then
    26.             Throw New System.ComponentModel.Win32Exception(CInt(Result))
    27.         End If
    28.     End Sub

    so then when you want to map a network drive you can simply do this:

    vb Code:
    1. 'This example maps the R drive to \\SomeServer\SomeShare
    2. Try
    3.      MapNetworkDrive("\\SomeServer\SomeShare", "R"c, False)
    4. Catch ex As Exception
    5.      MessageBox.Show("The network drive could not be mapped for the following reason: " & ex.Message)
    6. End Try
    Last edited by chris128; Sep 11th, 2013 at 12:55 PM.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  2. #2

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Mapping a network drive

    Oh and here's a bonus - how to delete an existing mapped drive

    API Definitions:
    vb Code:
    1. Public Const CONNECT_UPDATE_PROFILE As UInteger = 1
    2. Public Const NO_ERROR As UInteger = 0
    3.  
    4. ''' <summary>
    5. ''' Deletes a connection to a network resource
    6. ''' </summary>
    7. ''' <param name="lpName">The name of the connection to delete (e.g drive letter)</param>
    8. ''' <param name="dwFlags">If this is a persistent connection set to CONNECT_UPDATE_PROFILE to prevent from being mapped again at next logon</param>
    9. ''' <param name="fForce">Delete connection even if files from this resource are still open</param>
    10. <DllImportAttribute("mpr.dll", EntryPoint:="WNetCancelConnectionW")> _
    11. Public Shared Function WNetCancelConnection(<InAttribute(), MarshalAsAttribute(UnmanagedType.LPWStr)> ByVal lpName As String, ByVal dwFlags As UInteger, <MarshalAsAttribute(UnmanagedType.Bool)> ByVal fForce As Boolean) As UInteger
    12. End Function

    and my .NET method that wraps up the API functionality:
    vb Code:
    1. ''' <summary>
    2. ''' Deletes an existing mapped network drive
    3. ''' </summary>
    4. ''' <param name="DriveLetter">The drive letter to delete, must be a network drive</param>
    5. ''' <param name="Force">Force the drive to be deleted even if files are still open on this drive</param>
    6. Public Shared Sub RemoveNetworkDrive(ByVal DriveLetter As Char, ByVal Force As Boolean)
    7.         Dim Result As UInteger = WNetCancelConnection(DriveLetter & ":", CONNECT_UPDATE_PROFILE, Force)
    8.         If Not Result = NO_ERROR Then
    9.             Throw New System.ComponentModel.Win32Exception(CInt(Result))
    10.         End If
    11. End Sub

    So once you have copied and pasted all that into your project you can do this to delete a mapped drive:
    vb Code:
    1. 'Deletes the F drive
    2. 'Throws an exception if F is not a network drive
    3. RemoveNetworkDrive("F"c, True)
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  3. #3
    Lively Member sk8er_boi's Avatar
    Join Date
    Jun 2010
    Posts
    65

    Re: Mapping a network drive

    this has been very useful to me, thx ! =)

  4. #4

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Mapping a network drive

    No worries, glad it was helpful
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  5. #5
    Junior Member
    Join Date
    Sep 2012
    Posts
    25

    Re: Mapping a network drive

    Sorry to revive... but I tried this out. The mapping works great so far but the delete is having issues.
    First this line: Public Const NO_ERROR as UInteger = 0 is coming up as a problem saying its already declared in this class.
    So I commented that out.

    Then when I try to delete a mapped drive it will cause issues and lock up.
    This is what I get.
    PInvokeStackImbalance was detected
    Message: A call to PInvoke function 'blahblah::WNetCancelConnection' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.


    Any help with this would be nice. If we can't figure it out im sure i can delete mapped drives some other way.

  6. #6

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Mapping a network drive

    Well yeah the constant NO_ERROR is already declared in the first bit of code I posted on how to map a drive, so if you had already copied that and then copied the second part on removing a mapped drive as well then you'll obviously need to delete one of the NO_ERROR declarations.

    As for the stack imbalance error, I looked in the latest version of my Windows API library and this is how I've got it declared now (notice the entry point is WNetCancelConnection2W not WNetCancelConnectionW like in my original post):

    Code:
     ''' <summary>
        ''' Deletes a connection to a network resource
        ''' </summary>
        ''' <param name="lpName">The name of the connection to delete (e.g drive letter)</param>
        ''' <param name="dwFlags">If this is a persistent connection set to CONNECT_UPDATE_PROFILE to prevent from being mapped again at next logon</param>
        ''' <param name="fForce">Delete connection even if files from this resource are still open</param>
        <DllImport("mpr.dll", EntryPoint:="WNetCancelConnection2W", SetLastError:=True)> _
        Public Shared Function WNetCancelConnection(<InAttribute(), MarshalAsAttribute(UnmanagedType.LPWStr)> ByVal lpName As String, ByVal dwFlags As UInteger, <MarshalAsAttribute(UnmanagedType.Bool)> ByVal fForce As Boolean) As UInteger
        End Function
    and then to use it:

    Code:
     ''' <summary>
        ''' Deletes an existing mapped network drive
        ''' </summary>
        ''' <param name="DriveLetter">The drive letter to delete, must be a network drive</param>
        ''' <param name="Force">Force the drive to be deleted even if files are still open on this drive</param>
        Public Shared Sub RemoveNetworkDrive(ByVal DriveLetter As Char, ByVal Force As Boolean)
            Dim Result As UInteger = WNetCancelConnection(DriveLetter & ":", CONNECT_UPDATE_PROFILE, Force)
            If Not Result = NO_ERROR Then
                Throw New System.ComponentModel.Win32Exception(CInt(Result))
            End If
        End Sub
    If you want to skip having to define these things yourself etc you can just download the DLL I wrote that has all of these API definitions and .NET wrapper methods in it from my blog: http://blog.cjwdev.co.uk/2011/06/12/...-2-2-released/
    Last edited by chris128; Jun 5th, 2013 at 04:26 PM.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  7. #7
    Junior Member
    Join Date
    Sep 2012
    Posts
    25

    Re: Mapping a network drive

    Thank you, I took the old code out and put these both in.
    Now i get another error but its only when the drive it expects to be mapped is not mapped.
    I am guessing it has something to do with that no_error thing i commented out before.

    It happens in the second chunk of code at the "throw new system.componentmode1.win32exception(CInt(result)) line.
    The error says, A first chance exception of type 'system.componentmodel.win32exception' occurred.
    It also says, This network connection does not exist.

  8. #8

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Mapping a network drive

    No that's nothing to do with the NO_ERROR constant, that's an error that is being thrown for exactly the reason it says - you're trying to delete something that doesn't exist. You should loop through the current list of network drives and see if the drive exists before you try and delete it. See example below on how to loop through network drives:

    Code:
    For Each Drive As IO.DriveInfo In IO.DriveInfo.GetDrives()
                If Drive.DriveType = IO.DriveType.Network Then
                    MessageBox.Show("Drive " & Drive.Name & " is a network drive")
                End If
    Next
    If you wanted to check to see the actual UNC path that a network drive is mapped to you can use another function from my API library DLL that I linked to in the previous post like so:

    Code:
    MessageBox.Show(Cjwdev.WindowsApi.NativeFileSystem.GetUncPathFromNetworkDrive("H"c))
    That example would show you the UNC path that the H drive is mapped to - obviously if you wanted to work with a different drive letter you'd replace H with whatever letter you wanted. The lower case "c" after the letter H is just converting it from a String to a Char as I made that function only accept a single letter as the parameter, so that there was no confusion over how the drive letter should be specified (as it people could think it should be "H" or "H:" or "H:\")
    Last edited by chris128; Jun 6th, 2013 at 11:24 AM.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  9. #9
    Junior Member
    Join Date
    Sep 2012
    Posts
    25

    Re: Mapping a network drive

    Ok so i just have to do a check it sounds like to make sure the drives i will be using are mapped before trying to delete.

    I didnt know if your code already would counter that or not. Sounds good.

  10. #10
    New Member
    Join Date
    Sep 2013
    Posts
    2

    Re: Mapping a network drive

    I am using your .NET Windows API library, and I am loving it. I ran into a problem, though, when I recently upgraded to Windows 7 64-bit. I get no errors when the MapNetworkDrive function runs, then my "If Drive Exists Then Start Explorer" statement fires and Explorer states the drive doesn't exist.

    Is there a 64-bit version of your API library?

    Thanks,
    Carthax

  11. #11

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Mapping a network drive

    Quote Originally Posted by Carthax View Post
    I am using your .NET Windows API library, and I am loving it. I ran into a problem, though, when I recently upgraded to Windows 7 64-bit. I get no errors when the MapNetworkDrive function runs, then my "If Drive Exists Then Start Explorer" statement fires and Explorer states the drive doesn't exist.

    Is there a 64-bit version of your API library?

    Thanks,
    Carthax
    Is your program running "As Administrator" (aka with elevated permissions) ? If so then any drives you map will not be visible to explorer because explorer is running with different permissions. There's a registry entry you can set to change this behaviour but that's how it works by default. Its nothing to do with 64/32 bit and every program has the same issue (try using the Net Use command from an elevated command prompt and you'll have the same issue)
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  12. #12
    New Member
    Join Date
    Sep 2013
    Posts
    2

    Re: Mapping a network drive

    Quote Originally Posted by chris128 View Post
    Is your program running "As Administrator" (aka with elevated permissions) ? If so then any drives you map will not be visible to explorer because explorer is running with different permissions. There's a registry entry you can set to change this behaviour but that's how it works by default. Its nothing to do with 64/32 bit and every program has the same issue (try using the Net Use command from an elevated command prompt and you'll have the same issue)
    Interesting. You're absolutely right. My code requires that the app run as administrator, and it does appear to map the drive as administrator (as expected), but it is running Explorer as a non-elevated user (completely unexpected). Let me see what I can do about that. ...and I wonder how many of the other folks asking about that on Google are having the same problem...? Thanks for the help!

  13. #13

    Thread Starter
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: Mapping a network drive

    It runs explorer non-elevated because you're not actually launching a new instance of explorer.exe (as that's a single instance application) - if you try to start explorer.exe when one instance of it is already running in your session then it just opens an explorer window from that existing explorer.exe process.

    Oh and yes you'll find plenty of results on google about the mapped drives not persisting from elevated apps to non elevated apps
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width