我们公司有一个共享点文档服务器,其中 UNC 如下所示:\\theserver.ourdomain.com\rootdirectory
目前,此驱动器已映射到我本地计算机上的 Z:\。要访问 Z:\,您必须指定(每次登录时)凭据(在我们的例子中是我们登录时使用的用户名和密码)才能访问根目录中的文件夹和文件。
我处于需要将文件复制到共享点服务器的情况。我希望能够在不使用映射网络驱动器的情况下将文件复制到服务器上(不必在路径中指定 Z:\)。如何提供凭据以便我可以执行基本的 IO 功能,如 GetDirectories()、GetFiles()、IO.File.Copy() 等...?
我研究了以下内容,但未能成功:
- 通过指定纯文本用户名和密码来调用LogonUser API,然后从该调用中获取令牌并使用 WindowsIdentity 类的新实例模拟该用户。能够获得令牌,但模拟似乎不起作用。不断收到拒绝访问错误。
CredUIPromptForCredentials / CredUIPromptForWindowsCredentials API 调用,但我意识到这些只是用于一个花哨的 Windows UI,您可以在其中输入您的凭据,实际上什么也不做。
<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