2012-06-12 3 views
2

Наша компания имеет сервер точку документа, где доля UNC выглядит примерно так: \\ theserver.ourdomain.com \ RootDirectoryДоступ к файлам на сервере Указав мандатной

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

Я в ситуации, когда мне нужно скопировать файлы на сервер точек доступа. Я хочу, чтобы иметь возможность копировать файлы на сервер без использования подключенного сетевого диска (не нужно указывать Z: \ в пути). Как я могу предоставить учетные данные, чтобы я мог выполнять основные функции ввода-вывода, такие как GetDirectories(), GetFiles(), IO.File.Copy() и т. Д. ...?

Я посмотрел на следующие вещи, но не удалось сделать их работу:

  1. LogonUser API вызов, указав обычный текст имя пользователя и пароль, а затем принимает маркер от этого вызова и выдает себя, что пользователь с помощью новый экземпляр класса WindowsIdentity. Был способен получить токен, но олицетворение, похоже, не сработало. Уязвимость в доступе запрещена.
  2. CredUIPromptForCredentials/CredUIPromptForWindowsCredentials API-вызовы API, но я понимаю, что это просто фантастический пользовательский интерфейс Windows, где вы можете ввести свои учетные данные и фактически ничего не делать.

    <DllImport("advapi32.dll", SetLastError:=True)> _ 
    Private Shared Function LogonUser(lpszUsername As String, lpszDomain As String, _ 
                  lpszPassword As String, dwLogonType As Integer, _ 
                  dwLogonProvider As Integer, ByRef phToken As IntPtr) As Boolean 
    End Function 
    
    <DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _ 
    Private Shared Function CloseHandle(handle As IntPtr) As Boolean 
    End Function 
    
    '// logon types 
    Public Const LOGON32_LOGON_NETWORK As Integer = 3 
    Public Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9 
    
    '// logon providers 
    Public Const LOGON32_PROVIDER_WINNT50 As Integer = 3 
    Public Const LOGON32_PROVIDER_WINNT40 As Integer = 2 
    Public Const LOGON32_PROVIDER_WINNT35 As Integer = 1 
    Public Const LOGON32_PROVIDER_DEFAULT As Integer = 0 
    
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 
        Dim token = IntPtr.Zero 
        Dim success = LogonUser("username", "domain", "password", _ 
              LOGON32_LOGON_NEW_CREDENTIALS, _ 
              LOGON32_PROVIDER_DEFAULT, token) 
    
        If Not success Then 
         Me.RaiseLastWin32Error() 
        End If 
    
        Using identity = New WindowsIdentity(token) 
         Using impersonated = identity.Impersonate() 
          Try 
           Dim info = New DirectoryInfo("\\theserver.ourdomain.com\rootdirectory\") 
           Dim files = info.GetDirectories() 
          Catch ex As Exception 
          Finally 
           impersonated.Undo() 
          End Try 
          If Not CloseHandle(token) Then 
           Me.RaiseLastWin32Error() 
          End If 
         End Using 
        End Using 
    
    End Sub 
    
    Private Sub RaiseLastWin32Error() 
        Dim hr = Marshal.GetLastWin32Error() 
        Dim ex = Marshal.GetExceptionForHR(hr) 
    
        If ex IsNot Nothing Then 
         Throw ex 
        End If 
        Throw New SystemException(String.Format("Call resulted in error code {0}", hr)) 
    End Sub 
    
+0

Возможный дубликат [Переместить файл на сетевой ресурс (через олицетворение) C#] (http://stackoverflow.com/questions/5960937/move-file-onto-network-share-via-impersonation-c-sharp) –

+0

Дополнительный ресурс MSDN: http://msdn.microsoft.com/en-us/library/chf6fbt4.aspx. Понимая, что вы уже пробовали это (# 1 в своем сообщении), вам может потребоваться фактически показать код, чтобы диагностировать, почему вы получаете исключения. –

+0

Добавлен код для сообщения выше – test

ответ

0

Ну, я смог решить это с помощью WNetAddConnection2 API. Этот API также используется для сопоставления сетевых дисков, однако вы можете вызвать этот метод без указания буквы диска, чтобы он просто добавил соединение.

Скажем, например, у вас был диск X: сопоставлен с \\ сервером \ share Позволяет также сказать, что для доступа к файлам на сервере требуется имя пользователя &. При перезагрузке Windows 7 вы, вероятно, потеряете это соединение (вы получите уведомление о том, что Windows не смогла повторно подключить некоторые сетевые диски). Если у вас есть приложение, требующее доступа к файлам этого сервера, и вы пытаетесь получить к нему доступ без предоставления ваших учетных данных, вы получите доступ к запрещенным исключениям. Если вы сделаете успешный вызов WNetAddConnection2, он не только исправит ваш неподключенный сетевой диск, вы также сможете получить доступ к файлам/каталогам через пространство имен System.IO.

Мы используем Sharepoint, и это сработало для меня. Спасибо другим парням за ответ.

0

Это не является прямым ответом на ваш вопрос, как это дико другой подход. Если это не помогает в вашей ситуации, извините, что беспокоиться, но считаете ли вы, что используете веб-службы SharePoint для загрузки файлов и получения информации?

Я предлагаю этот подход к нескольким причинам:

  1. вопрос вы испытываете может происходить потому, что SharePoint реализует WebDav, который не может быть 100% совместимость с System.IO. Я не эксперт по внутренности здесь, я точно не знаю о совместимости, но это кажется правдоподобным.
  2. Местоположение UNC, которое вы можете легко поместить в URL-адрес, который требуется веб-службе.
  3. Вы можете установить учетные данные непосредственно на прокси и, возможно, иметь более легкое время. (Хотя мы делаем эти звонки с другого веб-сервера и поэтому приложение пула учетных данных в примере достаточно хороши для нас)

Вот некоторые продезинфицировать и упрощенный код на всякий случай:

// location takes the form http://server.name.com/site/library/folder/document.ext 

public string UploadDocument(string location, byte[] fileContents) 
{ 
    var result = String.empty; 
    var destination = new string[1]; 
    destination[0] = location; 
    var fileName = Path.GetFileName(location); 
    var fieldInfo = new FieldInformation[0]; 
    CopyResult[] copyResults; 

    _copyService.Url = "http://server.name.com/_vti_bin/Copy.asmx"; 
    _copyService.Credentials = CredentialCache.DefaultCredentials; 
    _copyService.CopyIntoItems(fileName, destination, fieldInfo, fileContents, out copyResults); 

    var errorCode = copyResults[0].ErrorCode; 
    if (errorCode != CopyErrorCode.Success) 
    { 
     if (errorCode == CopyErrorCode.DestinationCheckedOut) 
      result = "File is currently checked out. Please try again later."; 
     else 
      result = "Error uploading content."; 
    } 

    return result; 
} 

_copyService является зависимость, которую мы вводим, где реализация времени выполнения является прокси-сервером, созданным с помощью инструментов Visual Studio веб-службы Copy.asmx SharePoint.

Вы также можете получить содержимое папки и метаданные документа, используя веб-службу Lists.asmx. Наибольшие недостатки этого подхода заключаются в том, что для запроса информации требуется некоторое знание CAML, и обработка результатов не так проста. Но службы обоснованно документированы в MSDN, и все операции работают в нашем приложении.

+0

Спасибо за ответ. Я могу получить доступ к файлам и каталогам через код, если я (через Проводник) поставляю свой пароль и имя пользователя на подключенный сетевой диск, после чего он запрашивает. Я также обеспокоен проблемами с производительностью, если я пошел по маршруту, который вы предлагаете. – test

+0

Интересно. Мне будет интересно узнать это решение, потому что я вижу, откуда вы исходите из-за угла обзора. – Chuck

Смежные вопросы