Convert a username to a SID string in C#/.NET

匿名 (未验证) 提交于 2019-12-03 02:14:01

问题:

There's a question about converting from a SID to an account name; there isn't one for the other way around.

How do you convert a username to a SID string, for example, to find out which HKEY_USERS subkey relates to a user of a given name?

回答1:

The podcast tells me I should ask, and answer, questions when they're not answered on SO already. Here goes.

The easy way, with .NET 2.0 and up, is this:

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

The hard way, which works when that won't, and works on .NET 1.1 also:

[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);   /// The method converts object name (user, group) into SID string. /// Object name in form domain\object_name. /// SID string. 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;             }         }     } } 


回答2:

The LookupAccountName() native method has the advantage of being able to be executed on a remote machine whereas the .NET methods can't be executed remotely.

Though the example doesn't show it LookupAccountName(null)



回答3:

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);         }       }     } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!