0

and thanks for reading.

I have tried many variations of the following code, and all have returned a null value for the userAccountControl property:

DirectoryEntry de = new DirectoryEntry("LDAP://{my server/domain}"); 
DirectorySearcher ds= new DirectorySearcher(de);
ds.Filter = "(&(objectClass=user)(objectGUID=" + queryGUID + "))";
ds.PropertiesToLoad.Add("userAccountControl");
foreach (SearchResult sr in ds.FindAll())
{
var userFlags = sr.GetDirectoryEntry().Properties["userAccountControl"].Value;
int flags = (int)userFlags;
bool enabled = (flags & 0x2) == 0x2;
Console.WriteLine("Enabled: {0}", enabled ? "true" : "false");
}

Currently it's filtering using an objectGuid I retrieve from a valid user, converted into the proper form. (Being a test program I don't care about the string concatenation...I'll fix that in production code later.) I could (and have) use(d) other search filter values, including bitwise transitive filters. I've used direct binding versus a directory search. I've written a dozen or more variations of this, and all with the same result: the query succeeds but the userFlags property itself comes back null (is not present).

Since I'm specifically asking for a user class here, I know I'm not inadvertently getting a contact class (which wouldn't have the userAccountControl property). The bitwise operations shown in the code aren't important (I know I can convert to an enum and compare that way). It crashes with a null reference exception before the bitwise operations anyway.

This is running on Windows Server 2008 R2, using .NET 4 (I know of the issue with .NET 4.5 and AD account management). The account running this has both Administrator and Enterprise Administrator privileges. Also, as an aside, I downloaded Softerra's LDAP administrator console, and it as well doesn't show this property as present.

My question is simply why is this value null? It should not be, to my limited knowledge. Did I not set AD up properly in the beginning, perhaps? The search is improperly constructed?

Kenn
  • 31
  • 1
  • 4

2 Answers2

1

Is your code find user? If it s true can u try that?

//...
var results = ds.FindAll();
foreach (SearchResult sResult in results)
{
    var directoryEntry = sResult.GetDirectoryEntry();
    using (directoryEntry)
    {
        bool enabled;
        const string attrib = "userAccountControl";
        const int ufAccountDisable = 0x0002;
        de.RefreshCache(new string[] { attrib });
        var flags =(int)de.Properties[attrib].Value;
        if (((flags & ufAccountDisable) == ufAccountDisable))
        {
            enabled = false;
        }
        else
        {
            enabled true;
        }
    }
}

I use this code block. I tried it, after set disable a user in active directory. It must works correctly.

CocLn
  • 742
  • 10
  • 15
  • 1
    Thanks for responding. Your code also indicates the attribute value is null. I've learned that if I query my own account, the returned values are valid. If I query users I created using the Windows user management tools provided with Active Directory, the values are null or invalid. I added myself to the Domain Administrators group, figuring it was a permissions issue, but still no values. Since it works fine with my own account but not with other accounts, I now suspect some sort of permission or group policy issue versus a code issue. The code will run unattended, so I need to solve it. :) – Kenn Nov 11 '13 at 16:38
  • Yes you are rigth. Already if u try with normal user account u take an access denied error. But if you has admin account, it take all users status about disabled, locked or others – CocLn Nov 11 '13 at 17:05
1

Found it. It turns out that new user attributes are protected and can be accessed only by code running as administrator ("Run As"). I wasn't originally running this code using elevated privilege. Once I did, the attributes appeared. This seems to be similar behavior to querying for tombstoned objects. All I can say is "Doh!" :)

Kenn
  • 31
  • 1
  • 4