c# - 从 MVC 查询 Active Directory 结果为 : Attempted to access an unloaded appdomain.(HRESULT 异常:0x80131014)

标签 c# asp.net-mvc model-view-controller active-directory

我在 MVC 网络应用程序中使用 .Net 4 上的 c# 时遇到问题,当我查询 Active Directory 时,我经常收到错误:Attempted to access an unloaded应用程序域。 (HRESULT 的异常:0x80131014)。

奇怪的是,它会在一段时间内完美运行,然后它会开始发生,然后再次消失。

我对该函数进行了一些修改以使其正常工作,但它们似乎都失败了。我想知道我是否做错了什么,或者是否有更好的方法。

这是我当前的函数,它将接受一个 loginId 和一个 PrincipalContext。 loginId 可以是用户 DisplayName 即“John Smith”,也可以是 DOMAINNAME\josmi。默认是使用名字的前 2 个字母,然后是姓氏的前 3 个字母。如果不是这种情况,则在那里进行检查。这部分如果没问题。

public List<ADGroup> GetMemberGroups(string loginId, PrincipalContext principalContext, int tries = 0)
{
    var result = new List<ADGroup>();

    try
    {
        var samAccountName = "";
        if (loginId.Contains(" "))
        {
            var fName = loginId.Split(Char.Parse(" "))[0].ToLower();
            var sName = loginId.Split(Char.Parse(" "))[1].ToLower();

            if (sName.Trim().Length == 2)
                samAccountName = string.Format("{0}{1}", fName.StartsWith(".") ? fName.Substring(0, 4) : fName.Substring(0, 3), sName.Substring(0, 2));
            else
                samAccountName = string.Format("{0}{1}", fName.StartsWith(".") ? fName.Substring(0, 3) : fName.Substring(0, 2), sName.Substring(0, 3));
        }
        else
            samAccountName = loginId.Substring(loginId.IndexOf(@"\") + 1);

        var authPrincipal = UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, samAccountName);

        if (authPrincipal == null)
            throw new Exception(string.Format("authPrincipal is null for loginId - {0}", loginId));

        var firstLevelGroups = authPrincipal.GetGroups();

        AddGroups(firstLevelGroups, ref result);
    }
    catch
    {
        if (tries > 5)
            throw;

        tries += 1;

        System.Threading.Thread.Sleep(1000);
        GetMemberGroups(loginId, principalContext, tries);
    }

    return result;
}

    private void AddGroups(PrincipalSearchResult<Principal> principal, ref List<ADGroup> returnList)
    {
        foreach (var item in principal)
        {
            if (item.GetGroups().Count() > 0)
                AddGroups(item.GetGroups(), ref returnList);

            returnList.Add(new ADGroup(item.SamAccountName, item.Sid.Value));
        }
    }

这个函数是这样调用的:

MembershipGroups = ad.GetMemberGroups(user.SamAccountName, new PrincipalContext(ContextType.Domain));

有时得到的错误是:

System.AppDomainUnloadedException: Attempted to access an unloaded appdomain. (Exception from HRESULT: 0x80131014) at System.StubHelpers.StubHelpers.InternalGetCOMHRExceptionObject(Int32 hr, IntPtr pCPCMD, Object pThis) at System.StubHelpers.StubHelpers.GetCOMHRExceptionObject(Int32 hr, IntPtr pCPCMD, Object pThis) at System.DirectoryServices.AccountManagement.UnsafeNativeMethods.IADsPathname.Retrieve(Int32 lnFormatType) at System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo() at System.DirectoryServices.AccountManagement.ADStoreCtx.get_UserSuppliedServerName() at System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.BuildPathFromDN(String dn) at System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.MoveNextPrimaryGroupDN() at System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.MoveNext() at System.DirectoryServices.AccountManagement.FindResultEnumerator1.MoveNext() at System.DirectoryServices.AccountManagement.FindResultEnumerator1.System.Collections.IEnumerator.MoveNext()

最佳答案

通过 System.DirectoryServices.AccountManagement 的反射器查看内部类“UnsafeNativeMethods”是在 native 代码中实现的,所以 UserSuppliedServerName 向上一层是我可以在不查看 CLR VM 的情况下继续进行的所有操作,(坦率地说,我什至不确定如何这样做)似乎一个节点无法返回其主要组,所以也许考虑其他实现,经过一些谷歌搜索我发现这些可能有帮助

  • Active Directory and nested groups 这个可能很有前途这是代码示例..

        public IList<string> FindUserGroupsLdap(string username)
    { 
        // setup credentials and connection  
        var credentials = new NetworkCredential("username", "password", "domain");  
        var ldapidentifier = new LdapDirectoryIdentifier("server", 389, true, false); 
        var ldapConn = new LdapConnection(ldapidentifier, credentials); 
        // retrieving the rootDomainNamingContext, this will make sure we query the absolute root   
        var getRootRequest = new SearchRequest(string.Empty, "objectClass=*", SearchScope.Base, "rootDomainNamingContext");  
        var rootResponse = (SearchResponse)ldapConn.SendRequest(getRootRequest);   
        var rootContext = rootResponse.Entries[0].Attributes["rootDomainNamingContext"][0].ToString();  
        // retrieve the user 
        string ldapFilter = string.Format("(&(objectCategory=person)(sAMAccountName={0}))", username); 
        var getUserRequest = new SearchRequest(rootContext, ldapFilter, SearchScope.Subtree, null);  
        var userResponse = (SearchResponse)ldapConn.SendRequest(getUserRequest);     
        // send a new request to retrieve the tokenGroups attribute, we can not do this with our previous request since 
        // tokenGroups needs SearchScope.Base (dont know why...)  
        var tokenRequest = new SearchRequest(userResponse.Entries[0].DistinguishedName, "(&(objectCategory=person))", SearchScope.Base, "tokenGroups");  
        var tokenResponse = (SearchResponse)ldapConn.SendRequest(tokenRequest);  
        var tokengroups = tokenResponse.Entries[0].Attributes["tokenGroups"].GetValues(typeof(byte[])); 
        // build query string this query will then look like (|(objectSid=sid)(objectSid=sid2)(objectSid=sid3))  
        // we need to convert the given bytes to a hexadecimal representation because thats the way they   
        // sit in ActiveDirectory  
        var sb = new StringBuilder();  
        sb.Append("(|");   
        for (int i = 0; i < tokengroups.Length; i++)  
        {  
            var arr = (byte[])tokengroups[i];    
            sb.AppendFormat("(objectSid={0})", BuildHexString(arr));   
        }   
        sb.Append(")");    
        // send the request with our build query. This will retrieve all groups with the given objectSid
        var groupsRequest = new SearchRequest(rootContext, sb.ToString(), SearchScope.Subtree, "sAMAccountName"); 
        var groupsResponse = (SearchResponse)ldapConn.SendRequest(groupsRequest); 
        // loop trough and get the sAMAccountName (normal, readable name)   
        var userMemberOfGroups = new List<string>();    
        foreach (SearchResultEntry entry in groupsResponse.Entries)    
        userMemberOfGroups.Add(entry.Attributes["sAMAccountName"][0].ToString());  
        return userMemberOfGroups;
    } 
    
    private string BuildHexString(byte[] bytes)
    {  
        var sb = new StringBuilder(); 
        for (int i = 0; i < bytes.Length; i++) 
        sb.AppendFormat("\\{0}", bytes[i].ToString("X2")); 
        return sb.ToString();
    }
    

这些更多是为了信息目的

关于c# - 从 MVC 查询 Active Directory 结果为 : Attempted to access an unloaded appdomain.(HRESULT 异常:0x80131014),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6605666/

相关文章:

c# - 如何返回包含给定*部分*组合的所有组合?

javascript - 过滤列表为空

javascript - 基本 openUI5 分割 View 应用程序

ios - 在我的 TabBarViewController 中,如何为 viewDidLoad 上的每个 subview Controller 设置一个实例变量?

c# - Visual Studio 2012 中专用访问器的替换

c# - 在不影响业务逻辑的情况下降低圈复杂度

javascript - 从 AJAX 调用重定向到索引后刷新索引

spring - 简单的JSp和servlet代码可以迁移到Spring框架吗?

C# Func<object> getObject 的目的是什么?

ASP.NET MVC : putting custom attributes into option tag in select list