Преобразование имени пользователя в строку SID в C # /. NET

Возник вопрос о преобразовании из SID к имени учетной записи; нет другого пути.

Как преобразовать имя пользователя в строку SID, например, чтобы узнать, какой подраздел HKEY_USERS относится к пользователю с заданным именем?


person crb    schedule 24.06.2009    source источник


Ответы (4)


Подкаст говорит мне, что я должен задавать вопросы и отвечать на них, если они еще не получили ответа на SO. Вот оно.

Самый простой способ с .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;
            }
        }
    }
}
person crb    schedule 24.06.2009
comment
Меня заинтриговало, почему я выбрал «f» в качестве переменной для NTAccount! - person crb; 25.06.2009
comment
который работает, когда это не будет ... никаких указателей на то, когда простой подход не будет работать, если у меня есть .NET 2.0? - person Rory; 02.03.2010
comment
Не то чтобы я извинился. Я, наверное, имел в виду только pre-2.0; Я полагаю, это сводится к тем же вызовам API Win32. - person crb; 04.03.2010
comment
Один из моих клиентов сообщает об исключении: некоторые или все ссылки на идентификационные данные не могут быть переведены, когда я использую первый метод, я не пробовал второй метод, но я просто оставляю свой комментарий здесь, чтобы кто-нибудь знал. - person joe; 17.12.2020

Преимущество собственного метода LookupAccountName() в том, что он может выполняться на удаленном компьютере, тогда как методы .NET не могут выполняться удаленно.

Хотя в примере это не показано LookupAccountName(null) ‹- это удаленная система для выполнения.

person Community    schedule 07.03.2014

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

/////////Дистанционный пульт:

            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("-----------------------------------");
            }
person Danil    schedule 13.02.2018
comment
Предположительно это работает только для локальных учетных записей пользователей? - person Cocowalla; 09.07.2020
comment
для удаленного компьютера почти то же самое - person Danil; 10.07.2020
comment
Ха, я понятия не имел, что WMI может работать с предметными областями, спасибо! - person Cocowalla; 10.07.2020

person    schedule
comment
Хотя ваш код может быть очевидным, все же плохая идея - предоставлять только дампы кода. Без пояснений и кода только ответы помечаются как некачественные и подлежат удалению. - person Nawed Nabi Zada; 21.04.2021
comment
@NawedNabiZada Это вопрос программиста к программистам. Мы не писатели ????. Я сам искал ответ на этот вопрос, нашел его и решил им поделиться. В моем примере имена переменных и функций говорят о себе все! - person KUL; 21.04.2021
comment
Вы не поверите, но я прокомментировал это только для того, чтобы вы знали о правилах SO. - person Nawed Nabi Zada; 21.04.2021