Search code examples
c#active-directorydirectoryentrydomaincontrollerdirectorysearcher

DirectoryEntry and Domain Controller


We had a script in Powershell where we manipulated the Active Directory. I programmed it now in C#. My collegues say that they had to specify the domain controller in PS because otherwise it can happen that you read with DC A and write on DC B which could cause problems.

Do I really have to specify the Domain Controller if I'm using DirectorySearcher to find an entry and manipulate it? Or does per definition the same Domain Controller is user for finding the object (DirectorySearcher) and saving it (CommitChanges)?

I do not think so, since I can only specify it in the searching part (DirectoryEntry object for the DirectorySearcher) but not when it is written back to the AD (CommitChanges). So I suppose that the same DC is used for writing like the one used for reading.

Below I have an example where I search for a specific entry and change a property.

string filter = "(proxyaddresses=SMTP:[email protected])";
string searchOU = "ou=Users,dc=abc,dc=com";

DirectoryEntry entry = new DirectoryEntry("LDAP://" + searchOU);
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = filter;
SearchResult result = search.FindOne();
search.Dispose();
entry.Close();

DirectoryEntry toContact = result.GetDirectoryEntry();    
toContact.Properties["showInAddressBook"].Value = addressbook; 
toContact.CommitChanges();
toContect.Close();

Solution

  • Might I recommend using the objects available in the System.DirectoryServices.AccountManagement namespace? It's a more recent addition to .NET and handles AD work much more gracefully. It's recently saved me a whole lot of heartache which the older DirectorySearcher way of doing things was in part causing. Let the framework take the strain! There are lots of really useful articles around on the web, such as here.

    As an example of how to use PrincipalContext for searching Active directory, try this:

    var adContext = new PrincipalContext(ContextType.Domain);
    var queryTemplateUser = new UserPrincipal(adContext);
    queryTemplateUser.SamAccountName = "HenryCrunn";
    var ldapSearcher = new PrincipalSearcher(queryTemplateUser);
    var searchResults = ldapSearcher.FindAll();