L'interrogation Active Directory à partir d'MVC résultat: Tenté d'accéder à un déchargé domaine d'application. (Exception de HRESULT: 0x80131014)
J'ai un problème à l'aide de c# sur .Net 4 dans une application web MVC, où quand j'ai une requête Active Directory, je fréquemment obtenez un message d'erreur: Tenté d'accéder à un déchargé domaine d'application. (Exception de HRESULT: 0x80131014).
La chose étrange est que cela fonctionne parfaitement pour un temps, et puis il va juste commencer à se produire, et puis tout simplement disparaître de nouveau.
J'ai fait quelques modifications à la fonction pour le faire fonctionner , mais ils semblent tous à l'échec. Je me demande si je fais quelque chose de mal, ou si il ya une meilleure façon de le faire.
Voici ma fonction actuelle, qui va accepter un identifiant de connexion, et un PrincipalContext. L'identifiant de connexion peuvent être à l'utilisateur DisplayName je.e "John Smith", ou DOMAINNAME\josmi. La valeur par défaut est d'utiliser les 2 premières lettres de leur prénom, et puis les 3 premières lettres de leur nom de famille. Il y a une case là-bas, si ce n'est pas le cas. Cette partie si bien.
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));
}
}
Cette fonction est appelée comme ceci:
MembershipGroups = ad.GetMemberGroups(user.SamAccountName, new PrincipalContext(ContextType.Domain));
La l'erreur que j'ai PARFOIS obtenir est:
Système.AppDomainUnloadedException:
Tenté d'accéder à un déchargé
domaine d'application. (Exception de HRESULT:
0x80131014) à
Système.StubHelpers.StubHelpers.InternalGetCOMHRExceptionObject(Int32
rh, IntPtr pCPCMD, Objet pThis) à
Système.StubHelpers.StubHelpers.GetCOMHRExceptionObject(Int32
rh, IntPtr pCPCMD, Objet pThis) à
Système.DirectoryServices.AccountManagement.UnsafeNativeMethods.IADsPathname.Récupérer(Int32
lnFormatType) à
Système.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo()
au
Système.DirectoryServices.AccountManagement.ADStoreCtx.get_UserSuppliedServerName()
au
Système.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.BuildPathFromDN(String
dn) à
Système.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.MoveNextPrimaryGroupDN()
au
Système.DirectoryServices.AccountManagement.ADDNLinkedAttrSet.MoveNext()
au
System.DirectoryServices.AccountManagement.FindResultEnumerator1.MoveNext()
1.System.Collections.IEnumerator.MoveNext()
at
System.DirectoryServices.AccountManagement.FindResultEnumerator
- Je vais avoir le même problème avec aléatoire
AppDomainUnloadedException
s lors de l'appel enS.DS.AM
et ne peut pas trouver une solution. Ici en espérant que la fixation d'une prime obtiendrez des globes oculaires sur ce... - Un truc qui au moins a travaillé pour moi, c'est quand vous initialisez le PrincipalContext passer le nom de domaine dans le constructeur. PrincipalContext domaine = new PrincipalContext(ContextType.Domaine,"AD");
- commentaire semble avoir fait le tour pour moi. J'ai eu le même message d'erreur et en passant dans le domaine semble avoir fait le tour.
Vous devez vous connecter pour publier un commentaire.
regarder à travers le réflecteur au Système.DirectoryServices.AccountManagement la classe interne "UnsafeNativeMethods" est mis en œuvre dans le code natif, donc UserSuppliedServerName d'un niveau est tout ce que je peux aller sur sans regarder le CLR VM, (franchement je ne sais pas encore comment le faire) il Semble qu'un nœud est le défaut de retour de son groupe principal, donc peut-être envisager d'autres implémentations, après un peu de googling ive viennent à travers ces qui peuvent aider à
Active Directory et les groupes imbriqués celui-ci peut être prometteur heres l'exemple de code..
Ceux-ci sont plus pour info fins
Je ne sais pas comment
PrincipalContext
est passé, ici, mais une chose que j'ai remarqué dans mon propre code et de la recherche, lorsque j'ai eu cette erreur, j'ai eu:Où
strUserName
a été à l'utilisateur, c'est à direDOMAIN\johndoe
Je appeler ce code (qui était dans une autre fonction) et le retour de l'
UserPrincipal
objet commeup
et de le transmettre à:result
ne serait pas nulle, mais après j'ai vérifié pour cette condition, j'ai vérifié siresult.Count() > 0
, et c'est quand il échouerait (parfois - même si j'ai pu re-créer les conditions, quand il arriverait en cliquant sur un onglet en particulier dans mon application qui a appelé ce code, même si le même code a été appelé onload de mon appli et pas eu de problèmes). LeMessage
propriété dansresult
étaitAttempted to access an unloaded appdomain. (Exception from HRESULT: 0x80131014)
.J'ai trouvé dans un poste similaire à ce que tout ce que j'avais à faire était de préciser le domaine dans mon
PrincipalContext
. Puisque je ne pouvais pas le code de la mine, comme nous déplacer notre code entre développement, de Test et de Production des environnements où ils ont des domaines différents pour chacun d'eux, j'ai été capable de le définir en tant queEnvironment.UserDomainName
:Cela se débarrasser de l'erreur, pour moi.
_context = new PrincipalContext(ContextType.Domain);
Changé pour cette:_context = new PrincipalContext(ContextType.Domain, Environment.UserDomainName);
Et cela a fonctionné.Cette question est la même que Détermine si l'utilisateur est dans le groupe d'ANNONCES pour .NET 4.0 application
Il semble être un bug dans l'outil ADSI qui a été résolu avec un correctif. Windows 7 SP1 et Windows Server 2008 R2 SP1 ne comprennent pas les fixer, alors il devra être déployé manuellement sur vos machines de développement et environnements de serveur.
http://support.microsoft.com/kb/2683913
Que vous pourriez mettre dans des coupes à cerner le problème. Que
Thread.Sleep
ne ressemble pas à quelque chose que l'on désire dans une application web 🙂Si vous obtenez des exceptions peut-être que vous pourriez traiter différemment.
Je pense votre domaine d'application est d'être recyclées tandis que AD est en train de faire ses vaudou. L'ajout de la journalisation de la
Application_End
pourrait également fournir quelques indices.essayer
Lorsqu'une exception se produit, vous appelle à nouveau la fonction de la catch-bloc (en fonction de la valeur de la tente), mais jeté sa valeur de retour - même si la deuxième ou la troisième... appelez-vous travaillé retourné un résultat vide à l'appelant d'origine.
J'ai changé de sorte que le résultat ne sera pas jeté... plus
Dans la deuxième fonction, vous n'avez jamais vérifié les principaux param null avant de commencer le foreach... j'ai changé aussi...
Et j'ai enlevé la récursivité de dans le bloc catch catch (bien que je ne suis pas vraiment sûr de savoir si ce changement n'a aucun effet réel).