2009-06-24 14 views

Trả lời

76

Podcast cho tôi biết tôi nên hỏi và trả lời các câu hỏi khi chúng chưa được trả lời trên SO. Đây rồi.

Cách dễ dàng, với .NET 2.0 trở lên, là thế này:

NTAccount f = new NTAccount("username"); 
SecurityIdentifier s = (SecurityIdentifier) f.Translate(typeof(SecurityIdentifier)); 
String sidString = s.ToString(); 

Cách cứng

, mà làm việc khi điều đó sẽ không, và hoạt động trên NET 1.1 thêm:

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
public static extern bool LookupAccountName([In,MarshalAs(UnmanagedType.LPTStr)] string systemName, [In,MarshalAs(UnmanagedType.LPTStr)] string accountName, IntPtr sid, ref int cbSid, StringBuilder referencedDomainName, ref int cbReferencedDomainName, out int use); 

[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
internal static extern bool ConvertSidToStringSid(IntPtr sid, [In,Out,MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid); 


/// <summary>The method converts object name (user, group) into SID string.</summary> 
/// <param name="name">Object name in form domain\object_name.</param> 
/// <returns>SID string.</returns> 
public static string GetSid(string name) { 
    IntPtr _sid = IntPtr.Zero; //pointer to binary form of SID string. 
    int _sidLength = 0; //size of SID buffer. 
    int _domainLength = 0; //size of domain name buffer. 
    int _use;  //type of object. 
    StringBuilder _domain = new StringBuilder(); //stringBuilder for domain name. 
    int _error = 0; 
    string _sidString = ""; 

    //first call of the function only returns the sizes of buffers (SDI, domain name) 
    LookupAccountName(null, name, _sid, ref _sidLength, _domain, ref _domainLength, out _use); 
    _error = Marshal.GetLastWin32Error(); 

    if (_error != 122) //error 122 (The data area passed to a system call is too small) - normal behaviour. 
    { 
     throw (new Exception(new Win32Exception(_error).Message)); 
    } else { 
     _domain = new StringBuilder(_domainLength); //allocates memory for domain name 
     _sid = Marshal.AllocHGlobal(_sidLength); //allocates memory for SID 
     bool _rc = LookupAccountName(null, name, _sid, ref _sidLength, _domain, ref _domainLength, out _use); 

     if (_rc == false) { 
      _error = Marshal.GetLastWin32Error(); 
      Marshal.FreeHGlobal(_sid); 
      throw (new Exception(new Win32Exception(_error).Message)); 
     } else { 
      // converts binary SID into string 
      _rc = ConvertSidToStringSid(_sid, ref _sidString); 

      if (_rc == false) { 
       _error = Marshal.GetLastWin32Error(); 
       Marshal.FreeHGlobal(_sid); 
       throw (new Exception(new Win32Exception(_error).Message)); 
      } else { 
       Marshal.FreeHGlobal(_sid); 
       return _sidString; 
      } 
     } 
    } 
} 
+1

Tôi tò mò về lý do tại sao tôi chọn 'f' làm biến cho NTAccount! – crb

+1

"hoạt động khi điều đó sẽ không" ... bất kỳ gợi ý nào khi phương pháp tiếp cận dễ dàng sẽ không hoạt động, giả sử tôi có .NET 2.0? – Rory

+0

Không phải là tôi nhớ xin lỗi. Tôi có thể chỉ có trước 2.0; Tôi hy vọng nó sẽ giảm xuống cùng các cuộc gọi API Win32. – crb

1

Phương thức gốc LookupAccountName() có lợi thế là có thể được thực thi trên một máy từ xa trong khi các phương thức .NET không thể được thực thi từ xa.

Mặc dù ví dụ không hiển thị số LookupAccountName(null) < - đây là hệ thống từ xa để thực thi.

0
using System; 
using System.Management; 
using System.Windows.Forms; 

namespace WMISample 
{ 
public class MyWMIQuery 
{ 
    public static void Main() 
    { 
     try 
     { 
      ManagementObjectSearcher searcher = 
       new ManagementObjectSearcher("root\\CIMV2", 
       "SELECT * FROM Win32_UserAccount where name='Galia'"); 

      foreach (ManagementObject queryObj in searcher.Get()) 
      { 
       Console.WriteLine("-----------------------------------"); 
       Console.WriteLine("Win32_UserAccount instance"); 
       Console.WriteLine("-----------------------------------"); 
       Console.WriteLine("Name: {0}", queryObj["Name"]); 
       Console.WriteLine("SID: {0}", queryObj["SID"]); 
      } 
     } 
     catch (ManagementException e) 
     { 
      MessageBox.Show("An error occurred while querying for WMI 
      data: " + e.Message); 
     } 
     } 
    } 
}