如何通过常用的System.IO类访问网络驱动器?

时间:2010-02-28 18:55:40

标签: .net vb.net filesystems io network-drive

我的软件处理文件的多个操作,现在我已经使用System.IO类编写了相关的函数。

我现在需要添加对网络驱动器的支持。使用映射非常有效(尽管Directory.GetFiles有点低,我不知道为什么),但我现在希望能够直接处理\\192.168.0.10\Shared Folder\MyDrive之类的路径。有没有办法处理这种类型的路径,除了将驱动器安装到可用的驱动器号,使用新生成的路径,然后卸载?

3 个答案:

答案 0 :(得分:24)

您可以直接在路径中使用UNC路径(以\\开头)。但是,您必须考虑此连接的凭据,这可能是棘手的部分。

有几种方法:

  1. 如果远程系统位于同一个域中,或者域之间存在信任关系,并且您的程序正在运行的用户具有适当的访问权限,那么它将“正常工作”。

  2. 您可以发出并执行net use命令(通过Windows net.exe程序)以使用特定的用户名和密码建立连接。请注意,在用户会话中运行的任何程序都可以使用连接,而不仅仅是您的应用程序。完成后,使用/DELETE命令删除连接。典型语法为:net use \\computername\sharename password /USER:domain\username

  3. 您可以P / Invoke WNetAddConnection2完成与net use相同的操作,而不会炮轰net.exe。通过将NULL传递为lpLocalName,不会分配驱动器号,但用户名和密码将应用于通过UNC路径进行的后续访问。 WNetCancelConnection2功能可用于断开连接。

  4. 您可以使用LogonUser标记P / Invoke LOGON32_LOGON_NEW_CREDENTIALS,然后进行模拟,为您的线程添加其他远程凭据。与#2和#3不同,对用户整个会话的影响会有所限制。 (在实践中,这很少有利于众所周知的WNetAddConnection2解决方案。)

  5. 以下是如何从VB.NET调用WNetAddConnection2的示例。

    Private Sub Test()
        Dim nr As New NETRESOURCE
        nr.dwType = RESOURCETYPE_DISK
        nr.lpRemoteName = "\\computer\share"
        If WNetAddConnection2(nr, "password", "user", 0) <> NO_ERROR Then
            Throw New Exception("WNetAddConnection2 failed.")
        End If
        'Code to use connection here.'
        If WNetCancelConnection2("\\computer\share", 0, True) <> NO_ERROR Then
            Throw New Exception("WNetCancelConnection2 failed.")
        End If
    End Sub
    
    <StructLayout(LayoutKind.Sequential)> _
    Private Structure NETRESOURCE
        Public dwScope As UInteger
        Public dwType As UInteger
        Public dwDisplayType As UInteger
        Public dwUsage As UInteger
        <MarshalAs(UnmanagedType.LPTStr)> _
        Public lpLocalName As String
        <MarshalAs(UnmanagedType.LPTStr)> _
        Public lpRemoteName As String
        <MarshalAs(UnmanagedType.LPTStr)> _
        Public lpComment As String
        <MarshalAs(UnmanagedType.LPTStr)> _
        Public lpProvider As String
    End Structure
    
    Private Const NO_ERROR As UInteger = 0
    Private Const RESOURCETYPE_DISK As UInteger = 1
    
    <DllImport("mpr.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function WNetAddConnection2(ByRef lpNetResource As NETRESOURCE, <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpPassword As String, <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpUserName As String, ByVal dwFlags As UInteger) As UInteger
    End Function
    
    <DllImport("mpr.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function WNetCancelConnection2(<[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpName As String, ByVal dwFlags As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal fForce As Boolean) As UInteger
    End Function
    

答案 1 :(得分:4)

使用正常的UNC路径(例如您提到的路径)对我来说非常适合。例如:

string[] dirs = Directory.GetDirectories(@"\\192.168.1.116\");

工作得很好。如果没有,您可能遇到安全问题。在这种情况下,你将不得不考虑模仿以解决这个问题。有关假冒的更多信息,请查看this

答案 2 :(得分:1)

您发布的UNC路径(\\192.168.0.10\Shared Folder\MyDrive)很奇怪。没有“驱动器”,这样的共享就像一个目录。您使用Directory.GetFiles(@"\\192.168.0.10\Shared Folder")