.NET 4.5-Fehler in UserPrincipal.FindByIdentity (System.DirectoryServices.AccountManagement)

Beim Testen unserer .NET 4.0-Anwendung unter .NET 4.5 ist ein Problem mit dem aufgetretenFindByIdentity Methode fürUserPrincipal. Der folgende Code funktioniert, wenn er in einer .NET 4.0-Laufzeitumgebung ausgeführt wird, schlägt jedoch unter .NET 4.5 fehl:

[Test]
public void TestIsAccountLockedOut()
{
    const string activeDirectoryServer = "MyActiveDirectoryServer";
    const string activeDirectoryLogin = "MyADAccount@MyDomain";
    const string activeDirectoryPassword = "MyADAccountPassword";
    const string userAccountToTest = "TestUser@MyDomain";
    const string userPasswordToTest = "WRONGPASSWORD";

    var principalContext = new PrincipalContext(ContextType.Domain, activeDirectoryServer, activeDirectoryLogin, activeDirectoryPassword);

    var isAccountLockedOut = false;
    var isAuthenticated = principalContext.ValidateCredentials(userAccountToTest, userPasswordToTest, principalContext.Options);
    if (!isAuthenticated)
    {
        // System.DirectoryServices.AccountManagement.PrincipalOperationException : Information about the domain could not be retrieved (1355).
        using (var user = UserPrincipal.FindByIdentity(principalContext, IdentityType.UserPrincipalName, userAccountToTest))
        {
            isAccountLockedOut = (user != null) && user.IsAccountLockedOut();
        }
    }
    Assert.False(isAuthenticated);
    Assert.False(isAccountLockedOut);
}

Hier ist die Ausnahmestapel-Ablaufverfolgung:

System.DirectoryServices.AccountManagement.PrincipalOperationException : Information about the domain could not be retrieved (1355).
at System.DirectoryServices.AccountManagement.Utils.GetDcName(String computerName, String domainName, String siteName, Int32 flags)   at System.DirectoryServices.AccountManagement.ADStoreCtx.LoadDomainInfo()   at 
System.DirectoryServices.AccountManagement.ADStoreCtx.get_DnsDomainName()   at System.DirectoryServices.AccountManagement.ADStoreCtx.GetAsPrincipal(Object storeObject, Object discriminant)   at 
System.DirectoryServices.AccountManagement.ADStoreCtx.FindPrincipalByIdentRefHelper(Type principalType, String urnScheme, String urnValue, DateTime referenceDate, Boolean useSidHistory)   at 
System.DirectoryServices.AccountManagement.ADStoreCtx.FindPrincipalByIdentRef(Type principalType, String urnScheme, String urnValue, DateTime referenceDate)   at 
System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithTypeHelper(PrincipalContext context, Type principalType, Nullable`1 identityType, String identityValue, DateTime refDate)   at 
System.DirectoryServices.AccountManagement.Principal.FindByIdentityWithType(PrincipalContext context, Type principalType, IdentityType identityType, String identityValue)   at 
System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext context, IdentityType identityType, String identityValue)   

Hat jemand anderes dieses Problem gesehen und gelöst? Wenn nicht, gibt es für uns eine bessere Möglichkeit, das zu überprüfenIsAccountLockedOut Status für ein Active Directory-Konto?

Zu Referenzzwecken befinden sich alle unsere Testcomputer im selben Subnetz. Es gibt separate ActiveDirectory-Server, auf denen Windows Server 2003, 2008 und 2012 in verschiedenen Domänenfunktionsmodi ausgeführt werden (siehe unten). Der Code funktioniert auf Computern mit .NET 4.0, schlägt jedoch auf Computern mit .NET 4.5 fehl.

Die drei .NET-Maschinen, auf denen wir den Code ausgeführt haben, sind:
- Windows 7 mit .NET 4.0
- Windows Vista mit .NET 4.5
- Windows Server 2012 mit .NET 4.5

Die Active Directory-Server, die wir ausprobiert haben, sind:
- Windows 2003 mit AD Domain Functional Mode auf Windows 2000 native eingestellt
- Windows 2003 mit AD Domain Functional Mode auf Windows Server 2003 eingestellt
- Windows 2008 mit AD Domain Functional Mode auf Windows 2000 native eingestellt
- Windows 2008 mit AD Domain Functional Mode auf Windows Server 2003 eingestellt
- Windows 2008 mit AD Domain Functional Mode auf Windows Server 2008
- Windows 2012 mit AD Domain Functional Mode auf Windows 2012 eingestellt

Alle diese Active Directory-Server sind als einfache Gesamtstruktur konfiguriert, und die Clientcomputer sind nicht Teil der Domäne. Sie werden nur zum Testen dieses Verhaltens verwendet und führen nur Active Directory aus.

EDIT - 9. Oktober 2012

Vielen Dank an alle, die geantwortet haben. Im Folgenden finden Sie einen C # -Befehlszeilenclient, der das Problem veranschaulicht, und eine von uns identifizierte kurzfristige Problemumgehung, bei der keine Änderungen an den Active Directory- und DNS-Konfigurationen erforderlich waren. Es scheint, dass die Ausnahme bei einer Instanz des PrincipalContext nur einmal ausgelöst wird. Wir haben die Ausgaben für einen .NET 4.0-Computer (Windows 7) und einen .NET 4.5-Computer (Windows Vista) aufgenommen.

using System;
using System.DirectoryServices.AccountManagement;

namespace ADBug
{
    class Program
    {
        static void Main(string[] args)
        {
            const string activeDirectoryServer = "MyActiveDirectoryServer";
            const string activeDirectoryLogin = "MyADAccount";
            const string activeDirectoryPassword = "MyADAccountPassword";
            const string validUserAccount = "[email protected]";
            const string unknownUserAccount = "[email protected]";

            var principalContext = new PrincipalContext(ContextType.Domain, activeDirectoryServer, activeDirectoryLogin, activeDirectoryPassword);

            // .NET 4.0 - First attempt with a valid account finds the user
            // .NET 4.5 - First attempt with a valid account fails with a PrincipalOperationException
            TestFindByIdentity(principalContext, validUserAccount, "Valid Account - First Attempt");
            // Second attempt with a valid account finds the user
            TestFindByIdentity(principalContext, validUserAccount, "Valid Account - Second Attempt");
            // First attempt with an unknown account does not find the user
            TestFindByIdentity(principalContext, unknownUserAccount, "Unknown Account - First Attempt");
            // Second attempt with an unknown account does not find the user (testing false positive)
            TestFindByIdentity(principalContext, unknownUserAccount, "Unknown Account - Second Attempt");
            // Subsequent attempt with a valid account still finds the user
            TestFindByIdentity(principalContext, validUserAccount, "Valid Account - Third Attempt");
        }

        private static void TestFindByIdentity(PrincipalContext principalContext, string userAccountToTest, string message)
        {
            var exceptionThrown = false;
            var userFound = false;
            try
            {
                using (var user = UserPrincipal.FindByIdentity(principalContext, IdentityType.UserPrincipalName, userAccountToTest))
                {
                    userFound = (user != null);
                }
            }
            catch (PrincipalOperationException)
            {
                exceptionThrown = true;
            }
            Console.Out.WriteLine(message + " - Exception Thrown  = {0}", exceptionThrown);
            Console.Out.WriteLine(message + " - User Found = {1}", userAccountToTest, userFound);
        }
    }
}

.NET 4.0-Ausgabe

Valid Account - First Attempt - Exception Thrown  = False
Valid Account - First Attempt - User Found = True
Valid Account - Second Attempt - Exception Thrown  = False
Valid Account - Second Attempt - User Found = True
Unknown Account - First Attempt - Exception Thrown  = False
Unknown Account - First Attempt - User Found = False
Unknown Account - Second Attempt - Exception Thrown  = False
Unknown Account - Second Attempt - User Found = False
Valid Account - Third Attempt - Exception Thrown  = False
Valid Account - Third Attempt - User Found = True

.NET 4.5-Ausgabe

Valid Account - First Attempt - Exception Thrown  = True
Valid Account - First Attempt - User Found = False
Valid Account - Second Attempt - Exception Thrown  = False
Valid Account - Second Attempt - User Found = True
Unknown Account - First Attempt - Exception Thrown  = False
Unknown Account - First Attempt - User Found = False
Unknown Account - Second Attempt - Exception Thrown  = False
Unknown Account - Second Attempt - User Found = False
Valid Account - Third Attempt - Exception Thrown  = False
Valid Account - Third Attempt - User Found = True

Antworten auf die Frage(3)

Ihre Antwort auf die Frage