【问题标题】:How do I access a network drive through the usual System.IO classes?如何通过通常的 System.IO 类访问网络驱动器?
【发布时间】:2010-02-28 18:55:40
【问题描述】:

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

我现在需要添加对网络驱动器的支持。使用映射效果很好(虽然Directory.GetFiles 有点低,我也不知道为什么),但我现在希望能够直接处理诸如\\192.168.0.10\Shared Folder\MyDrive 之类的路径。除了将驱动器安装到可用驱动器号,使用新生成的路径,然后卸载之外,还有其他方法可以处理这种类型的路径吗?

【问题讨论】:

  • 您是否遇到了具体问题?处理 UNC 路径与映射驱动器应该没有什么不同。

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


【解决方案1】:

您可以直接在路径中使用 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. 您可以使用 LOGON32_LOGON_NEW_CREDENTIALS 标志 P/Invoke LogonUser,然后进行模拟以向您的线程添加其他远程凭据。与#2 和#3 不同,对用户整个会话的影响会更加有限。 (在实践中,这很少有利于众所周知的WNetAddConnection2 解决方案。)

以下是如何从 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

【讨论】:

    【解决方案2】:

    使用您提到的普通 UNC 路径非常适合我。例如:

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

    工作得很好。如果没有,您可能有安全问题或其他问题。在这种情况下,您将不得不考虑模仿来解决这个问题。查看this 了解更多关于模拟的信息。

    【讨论】:

    • 酷!事实上,我的代码有一个检查,在路径的开头修剪了反斜杠,当我尝试这个时导致了一个错误。谢谢! CFP。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-03
      • 2021-10-16
      • 2011-06-09
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      相关资源
      最近更新 更多