在其他用户和域下打开共享文件?

我有一个C#控制台应用程序需要读取另一个域中的计算机上的共享文件。 当应用程序尝试访问该文件时,由于本地用户无权访问共享资源,因此会发生exception。

目前我通过从运行中打开共享文件夹手动克服此问题,并将用户名和密码放入Windows身份validation对话框,然后运行该应用程序。

我怎么能以编程方式做到这一点?

a)使用LOGON32_LOGON_NEW_CREDENTIALS调用LogonUser并使用新令牌创建新的WindowsIdentity ,然后使用普通文件访问。

b)p /调用WNetAddConnection3 。 请注意,这使您的远程共享可以访问计算机上的其他每个进程。

c)通过System.ManagementCIM_DataFile WMI; 你甚至不需要p / invoke。 System.Management允许您指定远程计算机的凭据。

我使用点“a”作为“Anton”建议,我为一个类开发了两个版本,第一个使用Win32 API,第二个使用WindowsIdentity类

版本1:

 class UserImpersonation:IDisposable { [DllImport("advapi32.dll")] public static extern int LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool RevertToSelf(); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_LOGON_INTERACTIVE = 2; WindowsImpersonationContext wic; string _userName; string _domain; string _passWord; public UserImpersonation(string userName, string domain, string passWord) { _userName = userName; _domain = domain; _passWord = passWord; } public bool ImpersonateValidUser() { WindowsIdentity wi; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if (RevertToSelf()) { if (LogonUser(_userName, _domain, _passWord, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) { wi = new WindowsIdentity(tokenDuplicate); wic = wi.Impersonate(); if (wic != null) { CloseHandle(token); CloseHandle(tokenDuplicate); return true; } } } } if (token != IntPtr.Zero) CloseHandle(token); if (tokenDuplicate != IntPtr.Zero) CloseHandle(tokenDuplicate); return false; } #region IDisposable Members public void Dispose() { if(wic != null) wic.Dispose(); RevertToSelf(); } #endregion } 

版本2(来自MSDN,只有很小的变化)

 class UserImpersonation2:IDisposable { [DllImport("advapi32.dll")] public static extern bool LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern bool CloseHandle(IntPtr handle); WindowsImpersonationContext wic; IntPtr tokenHandle; string _userName; string _domain; string _passWord; public UserImpersonation2(string userName, string domain, string passWord) { _userName = userName; _domain = domain; _passWord = passWord; } const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_LOGON_INTERACTIVE = 2; public bool ImpersonateValidUser() { bool returnValue = LogonUser(_userName, _domain, _passWord, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle); Console.WriteLine("LogonUser called."); if (false == returnValue) { int ret = Marshal.GetLastWin32Error(); Console.WriteLine("LogonUser failed with error code : {0}", ret); return false; } Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No")); Console.WriteLine("Value of Windows NT token: " + tokenHandle); // Check the identity. Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name); // Use the token handle returned by LogonUser. WindowsIdentity newId = new WindowsIdentity(tokenHandle); wic = newId.Impersonate(); // Check the identity. Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name); return true; } #region IDisposable Members public void Dispose() { if(wic!=null) wic.Undo(); if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); } #endregion } 

怎么用(两者都一样)

  const string file = @"\\machine\test\file.txt"; using (UserImpersonation user = new UserImpersonation("user", "domain", "password")) { if (user.ImpersonateValidUser()) { StreamReader reader = new StreamReader(file); Console.WriteLine(reader.ReadToEnd()); reader.Close(); } } 

从内存中,您需要使用Windows API调用并以其他域上的用户身份登录。 请参阅此链接以获取示例。

另一个想法可能是使用RunAs命令行参数来读取文件并将其保存到本地域/服务器上的文件中。