在C#/.NET中将用户名转换为SID字符串

在C#/.NET中将用户名转换为SID字符串,c#,windows,identity,sid,C#,Windows,Identity,Sid,有一个问题是关于;没有另一条路可走 例如,如何将用户名转换为SID字符串,以找出哪个HKEY_USERS子项与给定名称的用户相关?播客告诉我,如果问题尚未得到回答,我应该提问并回答。来吧 对于.NET 2.0及更高版本,最简单的方法是: NTAccount f = new NTAccount("username"); SecurityIdentifier s = (SecurityIdentifier) f.Translate(typeof(SecurityIdentifier)); Strin

有一个问题是关于;没有另一条路可走


例如,如何将用户名转换为SID字符串,以找出哪个HKEY_USERS子项与给定名称的用户相关?

播客告诉我,如果问题尚未得到回答,我应该提问并回答。来吧

对于.NET 2.0及更高版本,最简单的方法是:

NTAccount f = new NTAccount("username");
SecurityIdentifier s = (SecurityIdentifier) f.Translate(typeof(SecurityIdentifier));
String sidString = s.ToString();
艰难之路,在无法实现的情况下也能实现,在.NET 1.1上也能实现:

[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;
            }
        }
    }
}
[DllImport(“advapi32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
公共静态外部bool LookupAccountName([In,marshallas(UnmanagedType.LPTStr)]字符串系统名,[In,marshallas(UnmanagedType.LPTStr)]字符串帐户名,IntPtr sid,ref int cbSid,StringBuilder referencedDomainName,ref int cbReferencedDomainName,out int use);
[DllImport(“advapi32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
内部静态外部bool ConvertSidToStringSid(IntPtr sid,[In,Out,marshallas(UnmanagedType.LPTStr)]参考字符串pStringSid);
///该方法将对象名称(用户、组)转换为SID字符串。
///“域\对象\名称”形式的对象名称。
///SID字符串。
公共静态字符串GetSid(字符串名称){
IntPtr _sid=IntPtr.Zero;//指向sid字符串二进制形式的指针。
int _sidLength=0;//SID缓冲区的大小。
int _domainLength=0;//域名缓冲区的大小。
int _use;//对象的类型。
StringBuilder _domain=new StringBuilder();//域名的StringBuilder。
int _误差=0;
字符串_sidString=“”;
//函数的第一次调用仅返回缓冲区的大小(SDI、域名)
LookupAccountName(null,name,_-sid,ref-sidLength,_-domain,ref-domainLength,out-use);
_error=Marshal.GetLastWin32Error();
if(_error!=122)//error 122(传递给系统调用的数据区域太小)-正常行为。
{
抛出(新异常(新的Win32Exception(_error.Message));
}否则{
_domain=new StringBuilder(_domainLength);//为域名分配内存
_sid=Marshal.AllocHGlobal(_sidLength);//为sid分配内存
bool\u rc=LookupAccountName(null,name,\u sid,ref\u sidLength,\u domain,ref\u domainLength,out\u use);
如果(_rc==false){
_error=Marshal.GetLastWin32Error();
自由世界元帅(_sid);
抛出(新异常(新的Win32Exception(_error.Message));
}否则{
//将二进制SID转换为字符串
_rc=ConvertSidToStringSid(_-sid,ref-sidString);
如果(_rc==false){
_error=Marshal.GetLastWin32Error();
自由世界元帅(_sid);
抛出(新异常(新的Win32Exception(_error.Message));
}否则{
自由世界元帅(_sid);
返回_sidString;
}
}
}
}

本机方法的优点是可以在远程计算机上执行,而.NET方法不能远程执行

虽然示例没有显示它
LookupAccountName(null)
/////////远程:

            ConnectionOptions connection = new ConnectionOptions();
            connection.Username = userNameBox.Text;
            connection.Password = passwordBox.Text;
            connection.Authority = "ntlmdomain:WORKGROUP";

            ManagementScope scope = new ManagementScope(
                "\\\\ASUS\\root\\CIMV2", connection);
            scope.Connect();

            ObjectQuery query= new ObjectQuery(
                "SELECT * FROM Win32_UserAccount"); 

            ManagementObjectSearcher searcher = 
                new ManagementObjectSearcher(scope, query);

            foreach (ManagementObject queryObj in searcher.Get())
            {
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("Win32_UserAccount instance");
                Console.WriteLine("-----------------------------------");
            }

我很好奇为什么我选择“f”作为NTAccount的变量!“当那不起作用时,它会起作用”。。。假设我有.NET2.0,有没有关于简易方法什么时候不起作用的指针?我记得没有,对不起。我可能只是指2.0之前的版本;我希望它可以归结为相同的Win32 API调用。我的一个客户端报告了一个异常:“当我使用第一个方法时,某些或所有标识引用都无法翻译”,我还没有尝试第二种方法,但我只是在这里留下我的评论供大家知道。大概这只适用于本地用户帐户?对于远程计算机,几乎是一样的。嗯,我不知道WMI可以用于域内容,谢谢!虽然您的代码可以是自解释的,但只提供代码转储仍然是一个坏主意。没有任何解释和代码,只有答案被标记为低质量,可以删除。@NawedNabiZada这是程序员向程序员提出的问题。我们不是作家信不信由你,我发表评论只是为了让你了解SO的规则。
            ConnectionOptions connection = new ConnectionOptions();
            connection.Username = userNameBox.Text;
            connection.Password = passwordBox.Text;
            connection.Authority = "ntlmdomain:WORKGROUP";

            ManagementScope scope = new ManagementScope(
                "\\\\ASUS\\root\\CIMV2", connection);
            scope.Connect();

            ObjectQuery query= new ObjectQuery(
                "SELECT * FROM Win32_UserAccount"); 

            ManagementObjectSearcher searcher = 
                new ManagementObjectSearcher(scope, query);

            foreach (ManagementObject queryObj in searcher.Get())
            {
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("Win32_UserAccount instance");
                Console.WriteLine("-----------------------------------");
            }
using System.Security.Principal;

var curUser = WindowsIdentity.GetCurrent().User.Value;
var otherUser = new WindowsIdentity("kul@mycompany.com").User.Value;