How to get/update 'Contacts' within Active

2019-01-14 10:31发布

问题:

is there a way to find and update the contacts in Active Directory? I'm building a sample C# .NET application to achieve this task. I would appreciate any code.

回答1:

Of course, you can do it in System.DirectoryServices.

I think what you really need is to learn how to use System.DirectoryServices. If you don't have a good book yet, I recommend this one.

It's not that hard, really. You just need to master two classes, DirectoryEntry and DirectorySearcher. DirectoryEntry is representing a LDAP object on the LDAP server. Assuming you have sufficient permissions, you can make changes on any LDAP object, including the contact object using DirectoryEntry. Each LDAP object has a number of attributes. TWo important attributes you need to know are objectCategory and objectClass. For the contact object, the objectCategory should be person and objectClass should be contact. You may also like to check the "targetAddress" attribute on the contact object, which stores the email address. There are a bunch of Exchange extended attributes on contact object. You probably like to check each of them one by one. To browse the objects on LDAP server, you can use a tool like AD Explorer or ADSI Edit

To do a search, you need to provider four things to DirectorySearcher.

  1. Search root
  2. LDAP search filter
  3. Search Scope
  4. Returned attributes

If your machine is already joined to a domain and you are logging in as a domain user, here is a sample on how to list out all contacts in your domain.

DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");
string domainContext = rootDSE.Properties["defaultNamingContext"].Value as string;
DirectoryEntry searchRoot = new DirectoryEntry("LDAP://" + domainContext);
using (DirectorySearcher searcher = new DirectorySearcher(
    searchRoot, 
    "(&(objectCategory=person)(objectClass=contact))", 
    new string[] {"targetAddress"}, 
    SearchScope.Subtree))
{
    foreach (SearchResult result in searcher.FindAll())
    {
        foreach (string addr in result.Properties["targetAddress"])
        {        
           Console.WriteLine(addr);
        }
        Console.WriteLine(result.Path);
    }
}

The first three lines are to help you to find the correct LDAP path to the root of your domain. It works only if you are logging in as a domain user. If you know the correct LDAP path of your domain, you can just feed it into DirectoryEntry directly.

I put all four parameters into DirectorySearcher. When you are getting familiar with Directory Services programming, you can skip some of them and .NET will provide a default value for you.

The result returned from DiectorySearcher is SearchResult. Note that SearchResult always return a collection of objects to you even though targetAddress is not a multivalue attribute. It's because some of the attributes on the LDAP object may be multi-value.

Another important information you can get from SearchResult is the Path. You can create a DirectoryEntry object using this Path later. To update your contact object, you need to use its Properties method and CommitChanges method.

DirectoryEntry de = new DirectoryEntry(result.Path);
de.Properties["targetAddress"].Value = "SMTP:jane.doe@foo.bar";
de.CommitChanges();

Finally, you can actually easily find a lot of online tutorial on both DirectorySearcher and DirectoryEntry. Try google it.



回答2:

I think you mean updating properties on a user object in Active Directory. And yes this is possible.

With .Net 3.5 we got the System.DirectoryServices.AccountManagement namespace which makes dealing with AD a lot simpler compared to what was in the System.DirectoryServices namespace before.

Typically to modify properties of a user (if you have access to save) you would do something like:

string sUserName = "someusertoload";
string sDomain = "test.local";
string sDefaultOU = "OU=test,DC=test,DC=local";
string sServiceUser = "userwithrights";
string sServicePassword = "somepassword";
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU,ContextOptions.SimpleBind, sServiceUser, sServicePassword);
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, sUserName);
oUserPrincipal.GivenName = "new givenname";
oUserPrincipal.Save();

You can find a some helper methods here.

Code sample for .Net 2.0 which retrieves a user with username "john" and updates the street address of the user. You might have to add credentials to the first line if the app running user don't have rights to edit content.

DirectoryEntry root = new DirectoryEntry("LDAP://server/DC=test,DC=local");
DirectorySearcher searcher = new DirectorySearcher( root, "(&(objectCategory=person)(objectClass=user)(sAMAccountName=john))" );
SearchResult result = searcher.FindOne();
DirectoryEntry user = result.GetDirectoryEntry();
user.Properties["streetAddress"][0] = "My Street 12";
user.CommitChanges();