You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForm获取Active Directory用户直接所属组及报错解决

获取AD用户直接隶属组时1355错误的解决方法

问题背景

使用C# Windows Form程序获取Active Directory用户的**直接隶属组(Member of,不含嵌套组)**时,调用GetGroups()方法仅对部分用户有效,多数用户触发错误:Information about the domain could not be retrieved (1355)。

原尝试代码:

public List<string> GetUserImmediateGroups(string userName)
{
    List<string> groupNames = new List<string>();

    using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
    {
        UserPrincipal user = UserPrincipal.FindByIdentity(ctx, userName);

        if (user != null)
        {
            // 获取用户直接隶属的组
            PrincipalSearchResult<Principal> userGroups = user.GetGroups();

            foreach (GroupPrincipal group in userGroups.OfType<GroupPrincipal>())
            {
                groupNames.Add(group.SamAccountName);
            }
        }

        return groupNames; // 返回直接组名称列表
    }
}

错误信息:

Information about the domain could not be retrieved (1355).

错误原因

  1. GetGroups()方法特性:该方法会自动解析嵌套组并尝试获取所有组的完整域信息,若部分组所在域无法被当前上下文访问(如跨域组、域控制器不可达),就会抛出1355错误。
  2. 默认PrincipalContext局限性:未指定具体域名时,上下文可能无法正确定位用户所在域,导致域信息检索失败。
  3. 权限或域控制器问题:程序运行账号无足够权限访问部分组的域信息,或目标域控制器离线/不可用。

解决方案

方法一:直接读取MemberOf属性(推荐)

MemberOf属性存储的是用户直接隶属组的DN(区分名),无需解析嵌套组,也不会触发跨域查询,彻底规避1355错误。

修改后代码:

public List<string> GetUserImmediateGroups(string userName)
{
    List<string> groupNames = new List<string>();

    using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
    {
        UserPrincipal user = UserPrincipal.FindByIdentity(ctx, userName);

        if (user != null)
        {
            // 获取MemberOf属性的原始值(直接组的DN)
            var memberOfValues = user.GetUnderlyingObjectProperties()["memberOf"];
            
            if (memberOfValues != null)
            {
                foreach (string dn in (IEnumerable)memberOfValues)
                {
                    // 从DN中提取组名(格式:CN=组名,OU=...)
                    int cnIndex = dn.IndexOf("CN=") + 3;
                    int commaIndex = dn.IndexOf(",", cnIndex);
                    if (cnIndex > 2 && commaIndex > cnIndex)
                    {
                        string groupName = dn.Substring(cnIndex, commaIndex - cnIndex);
                        groupNames.Add(groupName);
                    }
                }
            }
        }

        return groupNames;
    }
}

方法二:指定具体域名初始化PrincipalContext

若必须使用GetGroups()方法,明确指定用户所在域名,避免上下文自动解析出错:

// 替换为实际域名,例如"contoso.com"
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "your-domain-name"))
{
    // 后续逻辑保持不变
}

方法三:添加异常处理,跳过无法访问的组

若要保留GetGroups()逻辑,添加try-catch跳过出错的组,确保获取可用的组信息:

public List<string> GetUserImmediateGroups(string userName)
{
    List<string> groupNames = new List<string>();

    using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
    {
        UserPrincipal user = UserPrincipal.FindByIdentity(ctx, userName);

        if (user != null)
        {
            PrincipalSearchResult<Principal> userGroups = user.GetGroups();

            foreach (Principal principal in userGroups)
            {
                try
                {
                    if (principal is GroupPrincipal group)
                    {
                        groupNames.Add(group.SamAccountName);
                    }
                }
                catch (DirectoryServicesCOMException ex)
                {
                    // 跳过无法获取信息的组,可按需记录日志
                    if (ex.ErrorCode == 1355)
                    {
                        continue;
                    }
                    throw; // 其他异常重新抛出
                }
            }
        }

        return groupNames;
    }
}

说明

  • 方法一最可靠,完全贴合“仅获取直接组”的需求,无额外域查询操作。
  • 若需要组的更多属性(如描述、SID),可通过组的DN查询对应的GroupPrincipal,但需注意添加异常处理。

内容的提问来源于stack exchange,提问作者Kanishka Kularathna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:45:28