Slow AD property lookup in C #

Hi everyone, I am migrating my VBScript to C #. And I ran into a problem that finding Active Directory properties is much slower in C #.

This is my incomplete c # code

foreach(string s in dictLast.Keys)
{
    if(s.Contains("/"))
        str = s.Insert(s.IndexOf('/'), "\\");
    else
        str = s;
    dEntry = new DirectoryEntry("LDAP://" + str);
    strUAC = dEntry.Properties["userAccountControl"].Value.ToString();
    cmd.CommandText = "INSERT INTO [NOW](readTime) VALUES(\"" + test.Elapsed.Milliseconds.ToString() + "\")";
    cmd.ExecuteNonQuery();
    test.Reset();
    test.Start();
}

If I comment on this line. strUAC = dEntry.Properties ["userAccountControl"]. Value.ToString ();

It works after 11 seconds. But if I do not, it works for 2 minutes 35 seconds. The number of entries is 3,700. On average, each entry lasts 50 seconds. I use a stopwatch class.

My VBscript only works after 39 seconds (using time difference). With each entry, either 0 or 15 milliseconds. I am using Timer () difference.

Here is my vbscript

strAttributes = "displayName, pwdLastSet, whenCreated, whenChanged, userAccountControl"
For Each strUser In objList.Keys
    prevTime = Timer()
    strFilter = "(sAMAccountName=" & strUser & ")"
    strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
    adoCommand.CommandText = strQuery
    Set adoRecordset = adoCommand.Execute
    On Error Resume Next   
    If (adoRecordset.Fields("displayName") = null) Then
        strCN = "-"
    Else
        strCN   = adoRecordset.Fields("displayName")
    End If
    If (Err.Number <> 0) Then
        MsgBox(strUser)
    End If
    strCr8  = DateAdd("h", 8, adoRecordset.Fields("whenCreated"))
    strUAC  = adoRecordset.Fields("userAccountControl")
    If (strUAC AND ADS_UF_DONT_EXPIRE_PASSWD) Then
        strPW = "Never expires"
    Else
        If (TypeName(adoRecordset.Fields("pwdLastSet").Value) = "Object") Then
            Set objDate = adoRecordset.Fields("pwdLastSet").Value
            dtmPwdLastSet = Integer8Date(objDate, lngBias)
        Else
            dtmPwdLastSet = #1/1/1601#          
        End If
        If (dtmPwdLastSet = #1/1/1601#) Then
            strPW = "Must Change at Next Logon"
        Else
            strPW = DateAdd("d", sngMaxPwdAge, dtmPwdLastSet)
        End If
    End If
    retTime = Timer() - prevTime
    If (objList.Item(strUser) = #1/1/1601#) Then
        Wscript.Echo strCN & ";" & strUser & ";" & strPW & ";" & strCr8 & ";" & ObjChange.Item(strUser) & ";0;" & strUAC & ";" & retTime
    Else
        Wscript.Echo strCN & ";" & strUser & ";" & strPW & ";" & strCr8 & ";" & ObjChange.Item(strUser) & ";" & objList.Item(strUser) & ";" & strUAC & ";" & retTime
    End If
Next

Any ideas what the problem is? Please tell me if I do not give enough information. Thank.

DirectorySearcher. 1 min 8 sec

dEntry = new DirectoryEntry("LDAP://" + strDNSDomain);
string[] strAttr = {"userAccountControl"};
foreach(string s in dictLast.Keys)
{
    if(s.Contains("/"))
        str = s.Insert(s.IndexOf('/'), "\\");
    else
        str = s;
    ds = new DirectorySearcher(de, "(sAMAccountName=" + s + ")", strAttr, SearchScope.Subtree);
    ds.PropertiesToLoad.Add("userAccountControl");
    SearchResult rs = ds.FindOne();
    strUAC = rs.Properties["userAccountControl"][0].ToString();
    cmd.CommandText = "INSERT INTO [NOW](readTime) VALUES(\"" + test.Elapsed.Milliseconds.ToString() + "\")";
    cmd.ExecuteNonQuery();
    test.Reset();
    test.Start();
}

strDNSDomain NamingContext. , , 3 30 .

. , ?

using (var LDAPConnection = new DirectoryEntry("LDAP://domain/dc=domain,dc=com", "username", "password"))

"LDAP://dc = domain, dc = com".

. . lastLogon. StreamWriter.

+3
4

DirectoryEntry ADOConnection ADSI. .

, .

VBScript "displayName, pwdLastSet, whenCreated, whenChanged, userAccountControl" strAttributes. ADSI AD.

# RefreshCache, , . , DirectoryEntry.Properties RefreshCache() - . ADSI ( ), , .

, VBscript LDAP #, LDAP. DirectoryEntry.RefreshCache() LDAP. , 1000 , 1000 LDAP.

, VBscript

SELECT * FROM USER_TABLE

#

SELECT * FROM USER_TABLE WHERE id = @id

, # .

#, DirectorySearcher DirectoryEntry.

, DirectorySearcher.PropertiesToLoad, , LDAP. , .

+3

,

  • LDAP , . , , ..

  • System.DirectoryServices.Protocols, LDAP. . , .

  • .

+1

DirectorySearcher.PropertiesToLoad , .

, vbscript , .. - ,

DirectoryEntry de = new DirectoryEntry("ldap://domainname");
                    DirectorySearcher deSearch = new DirectorySearcher();
                    deSearch.SearchRoot = de;
                    deSearch.Filter = "(&(ObjectCategory=user)(sAMAccountName="+strUser+"))";
                    deSearch.PropertiesToLoad.Add("displayName");
                    deSearch.PropertiesToLoad.Add("pwdLastSet");
                    deSearch.PropertiesToLoad.Add("whenCreated");
                    deSearch.PropertiesToLoad.Add("whenChanged");
                    deSearch.PropertiesToLoad.Add("userAccountControl);


                    deSearch.SearchScope = SearchScope.Subtree;
                    SearchResult sr = deSearch.FindOne();
+1

:

If searchResult.Properties.Contains(PropertyName) Then
        Return searchResult.Properties(PropertyName)(0).ToString()
    Else
        Return String.Empty
End If
+1

Source: https://habr.com/ru/post/1790603/


All Articles