I have a machine within a domain (no work-group) and I have a local group Test Users
and within this group I have added domain users.
domain\\Administrator
domain\\Install
Now I want to fetch all the users from the group along with their SID
. With below code I am able to get all the user name within this group, but how to get SID
?
using (var groupEntry = new DirectoryEntry("WinNT://./Test Users,group"))
{
foreach (var member in (IEnumerable)groupEntry.Invoke("Members"))
{
using (var memberEntry = new DirectoryEntry(member))
{
Console.WriteLine(memberEntry.Name);
}
}
}
Alternate Solution
You asked if there was another way, for that i am posting a different process for looking up SIDs of accounts. Use Package Manager to get the nuget package: System.DirectoryServices.AccountManagement
.
Since MS came about with System.DirectoryServices.AccountManagement
, I have coded almost all the AD work with that assembly. Following is the code i wrote up for a different way of looking up SIDs for all members of groups/accounts in local group of a system.
// Recursively looks up all members and returns All the SIDs of all 'User' or 'local' accounts.
// ---> (NOT GROUPS but you can change that if you'd like.)
private static List<string> GetSidsForAllAccounts(GroupPrincipal grp)
{
List<string> listOfSids = new List<string>();
foreach (var member in grp.Members)
{
if (member.StructuralObjectClass != null && member.StructuralObjectClass.ToLower().Equals("group"))
listOfSids.AddRange(GetSidsForAllAccounts((GroupPrincipal)member));
else
listOfSids.Add(member.Sid.ToString());
// You could also use below to get Name and SID, PIPE delimited.
// listOfSids.Add($"{member.Name}|{member.Sid.ToString()}");
// You'll have to cast member to UserPrincipal if you are looking for properties specific to User Account.
}
return listOfSids;
}
Use in main method : You would call the above the following way.
// Look up the definition of PrincipalContext to use credentials.
// e.g. new PrincipalContext(ContextType.Machine, "domainName", "user", "pass");
PrincipalContext local = new PrincipalContext(ContextType.Machine);
GroupPrincipal grp = GroupPrincipal.FindByIdentity(local, "Administrators");
List<string> allSids = GetSidsForAllAccounts(grp);
allSids.ForEach(x => Console.WriteLine(x));
How does this work
PrincipalContext
defines where to look up the first group, which in this case is "Local Machine". PrincipalContext
of the group itself when it looks up the details. If the group belongs to Domain, it will look up using the domain context automatically and local machine if its a local machine group.To get the SID of the DirectoryEntry, you have to get the extended properties of the user/group. You can get these properties by calling .Properties
on the DirectoryEntry. You can access each of the properties by using ["propertyName"].Value
but for SID, you have to convert the SID's byte array to string. Below is the convert method from codeproject site and how to use this.
Method to convert Byte to String is taken from here
private static string ConvertByteToStringSid(Byte[] sidBytes)
{
StringBuilder strSid = new StringBuilder();
strSid.Append("S-");
try
{
// Add SID revision.
strSid.Append(sidBytes[0].ToString());
// Next six bytes are SID authority value.
if (sidBytes[6] != 0 || sidBytes[5] != 0)
{
string strAuth = String.Format
("0x{0:2x}{1:2x}{2:2x}{3:2x}{4:2x}{5:2x}",
(Int16)sidBytes[1],
(Int16)sidBytes[2],
(Int16)sidBytes[3],
(Int16)sidBytes[4],
(Int16)sidBytes[5],
(Int16)sidBytes[6]);
strSid.Append("-");
strSid.Append(strAuth);
}
else
{
Int64 iVal = (Int32)(sidBytes[1]) +
(Int32)(sidBytes[2] << 8) +
(Int32)(sidBytes[3] << 16) +
(Int32)(sidBytes[4] << 24);
strSid.Append("-");
strSid.Append(iVal.ToString());
}
// Get sub authority count...
int iSubCount = Convert.ToInt32(sidBytes[7]);
int idxAuth = 0;
for (int i = 0; i < iSubCount; i++)
{
idxAuth = 8 + i * 4;
UInt32 iSubAuth = BitConverter.ToUInt32(sidBytes, idxAuth);
strSid.Append("-");
strSid.Append(iSubAuth.ToString());
}
}
catch (Exception ex)
{
return "";
}
return strSid.ToString();
}
This is how you use that method and get the SID of the DirectoryEntry entity.
var coll = memberEntry.Properties;
object obVal = coll["objectSid"].Value;
object userSID;
if (null != obVal)
{
userSID = ConvertByteToStringSid((Byte[])obVal);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.