C# 如何使用列表视图显示该安全组中的安全组和用户?

C# 如何使用列表视图显示该安全组中的安全组和用户?,c#,active-directory,C#,Active Directory,我需要在列表视图中显示我的所有安全组以及属于这些安全组的用户 目前,我可以显示所有安全组,但不确定如何显示安全组中的用户 以下是我目前使用的代码: private void Security_group_btn_Click(object sender, EventArgs e) { DirectorySearcher searcher = new DirectorySearcher(DomainName); PrincipalContext ctx = n

我需要在
列表视图中显示我的所有安全组以及属于这些安全组的用户

目前,我可以显示所有安全组,但不确定如何显示安全组中的用户

以下是我目前使用的代码:

private void Security_group_btn_Click(object sender, EventArgs e)
    {
        DirectorySearcher searcher = new DirectorySearcher(DomainName);
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain, DomainName);
        UserPrincipal userPrin = new UserPrincipal(ctx);
        userPrin.Name = "*";
        var search = new System.DirectoryServices.AccountManagement.PrincipalSearcher();
        search.QueryFilter = userPrin;
        var results = searcher.FindAll();
        ListView lvwListView = this.security_listView;
        lvwListView.Clear();
        lvwListView.Columns.Add("Security Group", 175, HorizontalAlignment.Left);
        lvwListView.Columns.Add("Users", 175, HorizontalAlignment.Left);
        searcher.Filter = "(&(objectClass=group))";
        searcher.SearchScope = SearchScope.Subtree;
        searcher.PropertiesToLoad.Add("sAMAccountName");

        SearchResultCollection result = searcher.FindAll();
        foreach (SearchResult entry in result)
        {
            lvwListView.Items.Add(entry.GetDirectoryEntry().Properties["sAMAccountName"].Value.ToString());
        }
            result.Dispose();
            searcher.Dispose();
        }

    }
}
因此,基本上我希望在我的
列表视图中显示类似的内容:

Security Group          Name

Users                   User1
                        User2
                        User3
Administrators          User1
                        User2
                        User3
                        User4

谢谢

首先,请注意以下事项:

lvwListView.Items.Add(entry.GetDirectoryEntry().Properties["sAMAccountName"].Value.ToString());
特别是,使用仅获取一个值。当您使用获取一个值时,它会检查它是否已经在缓存中具有您要求的值。如果没有,它会要求AD为每个具有值的属性提供数据,这些数据通常比您实际需要的数据多得多。因为你在一堆账户上循环,这会大大降低你的速度

您已经在搜索结果中请求
sAMAccountName
,因为您使用了
searcher.PropertiesToLoad.Add(“sAMAccountName”)
,因此可以直接从
SearchResult
对象中提取值:

lvwListView.Items.Add((string) entry.Properties["sAMAccountName"][0]);
我在我写的一篇文章中更多地谈到了这一点

现在来实际回答您的问题:

获得会员是另一回事。您可以在搜索中请求
成员
属性,但当一个组的成员超过1500名时,您会遇到问题。你必须在页面中询问成员。但是,您还必须决定如何处理嵌套组:当组是组的成员时。是否只列出该组名称?或者你想看看这个小组的内部情况,把那些成员也找来

我也写了一整篇关于这一点的文章:

但很可能您可以使用我在那篇文章中展示的示例方法之一。这将获取一个组的
DirectoryEntry
对象,并为您提供一个字符串列表,其中包含组内每个对象的
DOMAIN\username
(如果需要,您可以更改)。您可以使用
recursive
参数来决定要对嵌套组执行的操作

public static IEnumerable<string> GetGroupMemberList(DirectoryEntry group, bool recursive = false) {
    var members = new List<string>();

    group.RefreshCache(new[] { "member" });

    while (true) {
        var memberDns = group.Properties["member"];
        foreach (string member in memberDns) {
            using (var memberDe = new DirectoryEntry($"LDAP://{member.Replace("/", "\\/")}")) {
                memberDe.RefreshCache(new[] { "objectClass", "msDS-PrincipalName", "cn" });

                if (recursive && memberDe.Properties["objectClass"].Contains("group")) {
                    members.AddRange(GetGroupMemberList(memberDe, true));
                } else {
                    var username = memberDe.Properties["msDS-PrincipalName"].Value.ToString();
                    if (!string.IsNullOrEmpty(username)) {
                        members.Add(username);
                    }
                }
            }
        }

        if (memberDns.Count == 0) break;

        try {
            group.RefreshCache(new[] {$"member;range={members.Count}-*"});
        } catch (COMException e) {
            if (e.ErrorCode == unchecked((int) 0x80072020)) { //no more results
                break;
            }
            throw;
        }
    }
    return members;
}
然后,您可以根据需要显示它们

如果您只在单个广告林中工作,这将很好地工作。但是,如果您的域信任林外的其他域,并且您可以期望在查看的组中看到来自这些域的用户,那么您需要对此进行说明。但我在那篇文章中谈到了这一点。我还介绍了那里的主要群体,你很少需要关心这些,但你可以

更新:要在
列表视图项中添加两列,必须单独创建它。您可以使用他们所称的“子项”的名称

您可以在循环中放入类似的内容,在循环中遍历成员,
groupName
是组的名称,
member
是组成员的名称

lvwListView.Items.Add(new ListViewItem(new [] {
                          groupName,
                          member
                      });

如果您只想在第一个组名上输入组名,那么您可以只输入一个空字符串(
“”
),而不是其他组名。

哇!谢谢你的回答!这对我来说是有道理的!但有一件事我一直在挣扎,那就是把它添加到我的listview中。你试过你提到的,但似乎不起作用?没关系,现在就开始起作用了。打字错误:-(谢谢。一切都在进行中谢谢,正在努力将Listview导出为PDF:-)但将继续处理:-)您好,我想知道您是否可以告诉我如何将此添加到我的列表视图?它可以工作,我可以看到每个组中的用户(再次感谢您的帮助),但是它显示有点错误,我认为这就是它不想导出为PDF的原因。你能在上面的代码中告诉我如何在ListView中显示信息吗?我用一些代码更新了我的答案,这些代码应该会有所帮助。
lvwListView.Items.Add(new ListViewItem(new [] {
                          groupName,
                          member
                      });