Подтвердить что ты не робот

Как получить доступ к сетевому диску через обычные классы System.IO?

Мое программное обеспечение обрабатывает несколько операций над файлами, и теперь я закончил писать связанные функции, используя классы System.IO.

Теперь мне нужно добавить поддержку сетевых дисков. Использование сопоставления работает очень хорошо (хотя Directory.GetFiles немного ниже, и я не знаю почему), но теперь я хотел бы иметь возможность напрямую обращаться с такими путями, как \\192.168.0.10\Shared Folder\MyDrive. Есть ли способ справиться с такими типами путей, кроме установки диска на доступную букву диска, с использованием вновь созданного пути, а затем размонтировать?

4b9b3361

Ответ 1

Вы можете использовать путь UNC (который начинается с \\) непосредственно на ваших путях. Однако вы должны учитывать учетные данные для этого соединения, что может быть сложной частью.

Существует несколько подходов:

  • Если удаленная система находится в том же домене или существует доверительная связь между доменами, а пользователь, с которым работает ваша программа, имеет подходящий доступ, он будет "просто работать".

  • Вы можете выложить и выполнить команду net use (через программу Windows net.exe), чтобы установить соединение с определенным именем пользователя и паролем. Имейте в виду, что соединение можно использовать любой программой, выполняемой в сеансе пользователя, а не только вашим приложением. Используйте команду /DELETE, чтобы удалить соединение, когда вы закончите. Типичный синтаксис: net use \\computername\sharename password /USER:domain\username.

  • Вы можете P/Invoke WNetAddConnection2 выполнить то же самое, что и net use, без обхода на net.exe. Передавая NULL как lpLocalName, никакая буква диска не назначается, но имя пользователя и пароль будут применяться к последующим обращениям, выполненным по пути UNC. Функция WNetCancelConnection2 может использоваться для разъединения.

  • Вы можете P/Invoke LogonUser с флагом LOGON32_LOGON_NEW_CREDENTIALS, за которым следует олицетворение, чтобы добавить дополнительные удаленные учетные данные в ваш поток. В отличие от # 2 и # 3, эффекты на весь сеанс пользователя будут немного более ограниченными. (На практике это редко делается в пользу известного решения WNetAddConnection2.)

Ниже приведен пример вызова WNetAddConnection2 из VB.NET.

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\");

Хорошо работает. Если это не так, у вас, вероятно, есть проблема с безопасностью или что-то еще. В этом случае вам придется искать олицетворение, чтобы обойти это. Проверьте этот для получения дополнительной информации о олицетворении.

Ответ 3

Путь UNC, который вы опубликовали (\\192.168.0.10\Shared Folder\MyDrive), является нечетным. Нет "диска", такой ресурс ведет себя как каталог. Вы должны использовать Directory.GetFiles(@"\\192.168.0.10\Shared Folder").