グループに所属する全てのメンバーを取得するサンプルを掲載します。サンプルでは、グループが循環参照している場合は、無限ループを発生しないように対処してあります。

動作環境

  • 実行環境:Windows 2003 Server (AD環境)
  • 開発環境:Visual Studio 2008 Professional
  • .NET 3.5 (.NET 2.0 以上でOK)

1. グループに所属するすべてのメンバーを列挙する

子グループも含めてすべてのグループのメンバーを列挙します。メンバーの取得には属性スコープクエリを使用しています。 GroupExpander.CreateGroupExpander メソッドを呼び出すことで、testGroupグループに属する全てのメンバーを列挙する処理を開始します。

class GroupExpander
{
    DirectoryEntry _expandRootGroup;
    IList<string> _groupMembers;
    IList<string> _processed;

    public IList<string> GroupMembers
    {
        get { return _groupMembers; }
    }
    public GroupExpander()
    {
    }
    public static void CreateGroupExpander()
    {
        using (DirectoryEntry group = GetEntry("CN=testGroup,CN=Users,DC=crm1,DC=local"))
        {
            GroupExpander expander = new GroupExpander();
            expander.ExpandGroup(group);
            foreach (string member in expander.GroupMembers)
            {
                Console.WriteLine(member);
            }
        }
    }
    public void ExpandGroup(DirectoryEntry expandRootGroup)
    {
        _expandRootGroup = expandRootGroup;
        _groupMembers = new List<string>();
        _processed = new List<string>();
        _processed.Add(_expandRootGroup.Properties["distinguishedName"].Value as string);
        Expand(_expandRootGroup);
    }
    /// <summary>
    /// DirectorySearcher の Attribute Scope Query を使用して、グループを展開する
    /// </summary>
    /// <param name="group"></param>
    private void Expand(DirectoryEntry group)
    {
        string[] properties = new string[]{"member", "distinguishedName", "objectClass"};
        DirectorySearcher ds = new DirectorySearcher(group, "(objectClass=*)", properties, SearchScope.Base);
        ds.AttributeScopeQuery = "member";
        using (SearchResultCollection searchResultCollection = ds.FindAll())
        {
            foreach (SearchResult result in searchResultCollection)
            {
                string dn = (string) result.Properties["distinguishedName"][0];
                if (!_processed.Contains(dn))
                {
                    _processed.Add(dn);
                    if (result.Properties["objectClass"].Contains("group"))
                    {
                        Expand(result.GetDirectoryEntry());
                    }
                    else
                    {
                        _groupMembers.Add(dn);
                    }
                }
            }
        }
    }
    public static DirectoryEntry GetEntry(string path)
    {
        return new DirectoryEntry("LDAP://" + path, null, null, AuthenticationTypes.Secure);
    }
}

サンプルでは、ドメインがcrm1.localのコンテナUsersに含まれるtestGroupに所属する全てのメンバーを取得しています。 

属性スコープクエリは.NET2.0以降で使用できます。.NET 1.1 の場合は、グループに属するグループを検索して、複数階層のメンバーを列挙する必要があります。

説明は以上です。 誤り、指摘点等がありましたらご連絡ください。