List local group members

564 Views Asked by At

I am trying to build a collection of all local groups and their respected members, however the challenge I am having with the listed code bellow is that "Administrators" group members is empty, all other groups on the server returns their members just not administrators. any ideas?

private void BuildGroupMembership(string remoteHost, string targetdomain, string userName, string password, bool domainOnly)
{
    var groupsList = new List<string>();
    PrincipalContext pContext = null;
    PrincipalContext searchContext = null;

    if (string.IsNullOrEmpty(remoteHost))
    {
        remoteHost = Environment.MachineName;
    }

    if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
    {
        pContext = new PrincipalContext(ContextType.Machine, remoteHost, null, ContextOptions.Negotiate, userName, password);
        searchContext = new PrincipalContext(ContextType.Domain, targetdomain, null, ContextOptions.Negotiate, userName, password);
    }
    else
    {
        pContext = new PrincipalContext(ContextType.Machine, remoteHost, null, ContextOptions.Negotiate);
        searchContext = new PrincipalContext(ContextType.Domain, targetdomain, null, ContextOptions.Negotiate);
    }
    try
    {
        var pSearcher = new PrincipalSearcher(new GroupPrincipal(pContext));
        foreach (var principal in pSearcher.FindAll().Where(principal => !groupsList.Contains(principal.Name))) groupsList.Add(principal.Name);
        foreach (var group in groupsList)
            try
            {
                var groupItem = new Group {GroupName = group};
                Groups.Add(groupItem);
                var grp = GroupPrincipal.FindByIdentity(pContext, group);
                if (grp != null)
                {
                    var allmembers = grp.GetMembers(false).ToList();
                    var members = domainOnly ? allmembers.Where(x => x.ContextType == ContextType.Domain).ToList() : allmembers.ToList();
                    foreach (var p in members)
                        try
                        {
                            var adGroup = GroupPrincipal.FindByIdentity(searchContext, IdentityType.Sid, p.Sid.Value);
                            if (adGroup != null)
                            {
                                groupItem.GroupMembers.Add(new GroupMember
                                {
                                    MemberDomain = adGroup.DistinguishedName.Substring(adGroup.DistinguishedName.IndexOf("DC="), adGroup.DistinguishedName.Length - adGroup.DistinguishedName.IndexOf("DC=")).Replace("DC=", "").Replace(",", "."),
                                    MemberName = p.SamAccountName,
                                    MemberSID = p.Sid.ToString(),
                                    IsGroup = true
                                });
                                continue;
                            }
                            var adUser = UserPrincipal.FindByIdentity(searchContext, IdentityType.Sid, p.Sid.ToString());
                            if (adUser != null)
                            {
                                groupItem.GroupMembers.Add(new GroupMember
                                {
                                    MemberDomain = adUser.DistinguishedName.Substring(adUser.DistinguishedName.IndexOf("DC="), adUser.DistinguishedName.Length - adUser.DistinguishedName.IndexOf("DC=")).Replace("DC=", "").Replace(",", "."),
                                    MemberName = p.SamAccountName,
                                    MemberSID = p.Sid.ToString(),
                                    IsGroup = false
                                });
                            }
                        }
                        catch
                        {
                            // ignored
                        }
                    grp.Dispose();
                }
            }
            catch
            {

            }
        pContext.Dispose();
        searchContext.Dispose();
    }
    catch (COMException ex)
    {
        throw new AuthenticationException(ex.Message);
    }
}
1

There are 1 best solutions below

0
On

This doen't answer completely your question but might help you. Using WMI is so much faster than using PrincipalContext, ... (at least in my case). In my app only Administrators and Users where needed.

static Regex partComponentRegex = new Regex("^[^:]+:Win32_UserAccount.Domain=\"(?<Domain>.+?)\",Name=\"(?<Name>.+?)\"$");

static IEnumerable<User> GetUsersFromSidType(WellKnownSidType wellKnownSidType)
{
    string gName = GetGroupName(wellKnownSidType);
    using (ManagementObjectSearcher groupSearcher = new ManagementObjectSearcher(
        string.Format("SELECT * FROM Win32_GroupUser WHERE GroupComponent =\"Win32_Group.Domain='{0}',Name='{1}'\"",
        Environment.MachineName,
        gName)))
   {

        foreach (var group in groupSearcher.Get())
        {
            Match m = partComponentRegex.Match(group["PartComponent"].ToString());
            if (m.Success)
            {
                using (ManagementObjectSearcher userSearcher = new ManagementObjectSearcher(
                    string.Format("SELECT * FROM Win32_UserAccount WHERE Name='{0}' AND Domain='{1}'",
                    m.Groups["Name"], m.Groups["Domain"])))
                { 
                    foreach (var user in userSearcher.Get())
                    {
                        yield return new User()
                        {
                            Disabled = (bool)user["Disabled"],
                            Domain = user["Domain"].ToString(),
                            FullName = user["FullName"].ToString(),
                            Name = user["Name"].ToString(),
                            SID = user["SID"].ToString()
                        };
                    }
                }
            }
        } 
    }
}

static string GetGroupName(WellKnownSidType wellKnownSidType)
{
    SecurityIdentifier sid = new SecurityIdentifier(wellKnownSidType, null);
    using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(
        string.Format("SELECT * FROM Win32_Group WHERE SID='{0}'",
        sid.Value)))
    {
        var e = searcher.Get().GetEnumerator();
        if (e.MoveNext())
            return e.Current["Name"].ToString();
        return null;
    }
}