简体   繁体   中英

Retrieve Active Directory GUID using employeeID

I am developing a program that will update certain active directory properties using HR data (retrieved from SQL Server). The 1st stage was to match using values like samAccountName, email, surname etc. and that has been successful.

Now I need to change the filtering, so that I can retrieve the relevant Active Directory entry using employee number which I believe is employeeID in Active Directory. I have been trying code such as:

dirSearcher.Filter = String.Format("(&(objectCategory=user)(employeeid={0}))", employeeId);

src = dirSearcher.FindAll();

try
{
    de = src[0].GetDirectoryEntry();
    textBoxResult.Text = de.Guid.ToString();
}
catch (Exception ex)
{
    textBoxResult.Text = ex.Message;
    activeDirectoryID = "";
}
return activeDirectoryID;

However, src is always null .

I did manage to get it working using:

PrincipalContext ctx = new PrincipalContext(ContextType.Domain, directoryRootPath, username, password);

UserPrincipal searchTemplate = new UserPrincipal(ctx);
searchTemplate.EmployeeId = HREmployeeNumber;
PrincipalSearcher ps = new PrincipalSearcher(searchTemplate);

UserPrincipal user = (UserPrincipal)ps.FindOne();

try
{
    activeDirectoryID = user.Guid.ToString();
}

However, this code is a lot slower. Originally, when it was matching on samAccountName or email address it processed just over 4000 records in about 5 minutes. In principal the code works, but takes 40 minutes.

Any advice?

Your query looks ok. The only thing I suspect is maybe your employeeId is an odd type that isn't getting cast to a string the way you expect. What type is it? When you debug the code, inspect dirSearcher.Filter after you set it and make sure it is what you expect it to be.

Apart from that, I can comment on performance. Using PrincipalSearcher is always slower than using DirectorySearcher directly (which is what PrincipalSearcher uses in the background anyway). The whole AccountManagement namespace does make things easier sometimes, but at the cost of control over performance.

This query will always be a little slow since employeeId is not an indexed attribute. So it has to go through every user account to find a match. You can speed this up a little by using FindOne() instead of FindAll() so that it stops after it finds one and doesn't keep trying to look for another match.

You're also better off asking for only objectGuid in the search results, since if you don't specify anything, it will return every attribute for each result.

Then you can use the value of objectGuid returned during the search instead of using GetDirectoryEntry() . The new DirectoryEntry object will go back out to AD and get the info again, which isn't necessary. The only real reason to use GetDirectoryEntry() is if you're going to update the object.

Here's an example of what I mean:

dirSearcher.Filter = String.Format("(&(objectCategory=user)(employeeid={0}))", employeeId);
dirSearcher.PropertiesToLoad.Add("objectGuid");

try
{
    var result = dirSearcher.FindOne();
    var guid = new Guid((byte[]) result.Properties["objectGuid"][0]);

    textBoxResult.Text = guid.ToString();
}
catch (Exception ex)
{
    textBoxResult.Text = ex.Message;
    activeDirectoryID = "";
}
return activeDirectoryID;

I go into more detail about that in an article I wrote about performance when talking to AD: Active Directory: Better performance

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM