2009-07-28 41 views
2

我有一个C#控制台应用程序需要读取另一个域中的计算机上的共享文件。 当应用程序试图访问文件时,由于本地用户没有访问共享资源的权限,因此发生异常。在其他用户和域下打开共享文件?

目前我手动解决了这个问题,从运行打开共享文件夹,并将用户名和密码放入Windows身份验证对话框中,然后运行应用程序。

如何以编程方式执行此操作?

回答

0

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

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

+0

我不能使用运行方式为两件事情在本地机器不包含此用户不属于任何域 第一件事,第二件事是文件是非常巨大的本地 – 2009-07-28 09:17:04

3

a)p/invoke LogonUserLOGON32_LOGON_NEW_CREDENTIALS并使用新令牌创建新的WindowsIdentity,然后使用普通文件访问。

b)p/invoke WNetAddConnection3。请注意,这会使您的远程共享可以访问您计算机上的所有其他进程。

c)通过System.ManagementCIM_DataFile的WMI;你甚至不需要p/invoke。 System.Management可让您指定远程机器的凭证。

+0

复制它的“A” msdn说 “你不能使用LogonUser登录到远程计算机” – 2009-07-28 09:18:20

+0

其实你可以 - 编辑 – 2009-07-28 09:36:16

2

我用了点“一”称为“安东”的建议,我开发了两个版本的一类,使用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(); 
       } 
      }