Accessing Files On Server By Specifying Credentials

Our company has a share point document server where the UNC looks something like this: theserver.ourdomain.comrootdirectory

Currently this drive is mapped to the Z: on my local computer. To access the Z: you have to specify (each time you login) credentials (in our case is it our username and password we logged on with) to access the folders and files in the rootdirectory .

I am in a situation where I need to copy files onto the share point server. I want to be able to copy files onto the server without using the mapped network drive (not have to specify Z: in the path). How can I supply credentials so that I can perform basic IO functions like GetDirectories(), GetFiles(), IO.File.Copy() etc...?

I have looked into the following things but was unsuccessful in making them work:

  • LogonUser API call by specifying plain text user name and password, then taking the token from that call and impersonating that user using a new instance of the WindowsIdentity class. Was able to get the token, but the impersonation didn't seem to work. Kept getting access denied errors.
  • CredUIPromptForCredentials/CredUIPromptForWindowsCredentials API calls, but I realize these are just for a fancy Windows UI where you can enter your credentials into and actually don't do anything.

    <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.comrootdirectory")
                    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
    

  • This isn't a direct answer to your question as it is a wildly different approach. If it doesn't work for your situation sorry to bother, but have you considered using the SharePoint web services to load the files and retrieve information?

    I suggest this approach for a few reasons:

  • The issue you are experiencing may be occurring because SharePoint implements WebDav which might not be 100% compatible with System.IO. I'm not an expert on the innards here, I don't know about the compatibility for sure, but it seems plausible.
  • The UNC location you have could easily be massaged into a URL that the web service requires.
  • You can set the credentials directly on the proxy and might have an easier time. (though we make these calls from another web server and so the app pool credentials in the example are good enough for us)
  • Here's some sanitized and simplified code just in case:

    // 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 is a dependency we inject where the run-time implementation is the proxy generated by Visual Studio tools from the Copy.asmx SharePoint web service.

    You can also get folder contents and document metadata using the Lists.asmx web service. The biggest downsides to this approach are that querying the information requires some CAML knowledge and processing the results is not as easy. But the services are reasonably documented on MSDN and the operations are all working in our application.


    Well, I was able to solve this with the help of the WNetAddConnection2 API. This API is used for mapping network drives as well, however you can call this method without specifying a drive letter so that it just adds the connection.

    Say for example you had drive X: mapped to servershare Lets also say that it requires username & password to access the files on the server. When you restart Windows 7, you will probably lose that connection (you will get a notification saying that Windows was unable to reconnect some of the network drives). If you have an application that requires access to that server's files and you attempt to access it without supplying your credentials you will get access denied exceptions. If you do a successful call to WNetAddConnection2, not only will it fix your unmapped network drive, you will also be able to access the files/directories via the System.IO namespace.

    We use Sharepoint and this worked for me. Thanks to the other guys for replying also.

    链接地址: http://www.djcxy.com/p/44174.html

    上一篇: 从Windows服务访问NFS共享

    下一篇: 通过指定凭证访问服务器上的文件