Как получить доступ к сетевому диску через обычные классы System.IO? - PullRequest
14 голосов
/ 28 февраля 2010

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

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

Ответы [ 3 ]

24 голосов
/ 28 февраля 2010

Вы можете использовать путь 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. Вы можете 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
4 голосов
/ 28 февраля 2010

Использование обычных путей UNC, таких как тот, который вы упомянули, прекрасно работает для меня. Например:

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

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

1 голос
/ 28 февраля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...