I can use vb.net or c# on this part of the project and i was hoping someone could tell me a little about updating an active directory field.

i found in searching system.directoryServices in google this bit of vb code.

user.Properties("title")(0) = employeeTitle.SelectedItem.Text

which i think is this in c#

user.Properties["title"][0] = employeeTitle.SelectedItem.Text;

but maybe its not that in c# and it be interesting to know as it might help me understand what is going on here better. My training is more in C# java and c++ , so vb pages i find on the web don't always connect with me. My confusion is what is the second [0] in c# or (0) in vb doing here.

More generally the question is if you have a directory entry, how do you update a property, say employee id or work phone. I believe all properties that i need exist on the users i'm writing to but some dont have any values set on them for that field.

thanks
Mike

Edited 3 Years Ago by Nick Evan: Fixed formatting

Here's how I would do it with VBScript:

strNewTitle = "New Title"
Set objUser = GetObject("LDAP://cn=johndoe,dc=acme,dc=com")
objUser.Put "title", strNewTitle
objUser.SetInfo

and with DirectoryServices and VB.NET:

Dim oUser As New DirectoryEntry()

' Set target
oUser.Path = "LDAP://CN=johndoe, DC=acme, DC=com"
' Set a new value to "title" property
oUser.InvokeSet("title", "New Title")
' Save changes
oUser.CommitChanges()
' Release resources
oUser.Close()

Just change the syntax to C# if you need to.

I didn't have any AD to test with so I suggest backing up AD and/or reading properties first before trying to change them. Just in case read about DirectoryEntry Class in MSDN. You may need to set AuthenticationType, Password etc. properties too.

HTH

i found this code

Depending on the attribute, the PropertyValueCollection (or ResultPropertyValueCollection) will return either a single value or multiple values.  To actually get a value from the DirectoryEntry, we need to cast the 'object' to whatever type we are expecting.  Thus, we get something like:

DirectoryEntry entry = new DirectoryEntry(...);
using (entry)
{
    if (entry.Properties.Contains("sn"))
    {
        string lastName = entry.Properties["sn"][0].ToString();
    }
}

In this example, I cast the 'sn' attribute to the lastname.  It makes 2 assumptions: 1.) The value can be interpreted as a string, and 2.) I am only interested in a single valued attribute.

The pattern changes slightly if we are looking to read the values from a multi-valued attribute:

DirectoryEntry entry = new DirectoryEntry(...);
using (entry)
{
    if (entry.Properties.Contains("mail"))
    {
        foreach (object o in entry.Properties["mail"])
        {
            //iterate through each value in the 'mail' attribute as a string
            Response.Output.Write("mail: {0}", o.ToString());
        }
    }
}

the ["propertyname"][0] seems to relate to if its a single value attribute ore multi value. ie if property is email. [0] assumes that there is only one value. if the person could have multiple emails under property 0 then i'd need to look at them all. Does this sound right?

Mike

the ["propertyname"][0] seems to relate to if its a single value attribute ore multi value. ie if property is email. [0] assumes that there is only one value. if the person could have multiple emails under property 0 then i'd need to look at them all. Does this sound right?

Yes it does. A user can have more than one email so the property ["email"] is an array of values i.e. you use notation ["email"][0]. But if there's a property which can have at most one value it would be stored as key/value pair and the notation is ["propertyname"] (for example ["title"] because user has one title).

it says under remarks: This method should not be used. The Properties property should be used to access the properties of the DirectoryEntry object.

I noticed that too. It would be too easy to use InvokeGet/InvokeSet I guess :)

Here's the rewritten code (in C# this time):

using System.Collections; // IDictionary
using System.DirectoryServices;

DirectoryEntry oUser = new DirectoryEntry();
System.DirectoryServices.PropertyCollection userProperties; // Notice: there's also System.Data.PropertyCollection

// Set target
oUser.Path = "LDAP://CN=johndoe, DC=acme, DC=com";
// Get properties of this user
userProperties = oUser.Properties;
// Check if "title" property (key) exists
if (userProperties.Contains("title"))
{
    // Set a new value in the dictionary for the "title" key
    // See: http://msdn.microsoft.com/en-US/library/system.directoryservices.propertycollection.system.collections.idictionary.item(v=VS.80).aspx
    ((IDictionary)userProperties)["title"] = "New Title";
}
else
{
    // Add a new key/value to dictionary
    // See: http://msdn.microsoft.com/en-US/library/system.directoryservices.propertycollection.system.collections.idictionary.add(v=VS.80).aspx
    ((IDictionary)userProperties).Add("title", "New Title");
}
// Save changes
oUser.CommitChanges();
// Release resources
oUser.Close();

DirectoryEntry.Properties returns an object of type PropertyCollection. Changing an AD property's value (or dealing with AD properties in general) means dealing with the PropertyCollection which inherits from IDictionary and ICollection (and IEnumerable).

Once again I didn't test the code against actual AD but the code seems to be sensible. If you need a more general solution, I suggest making some wrapper for the PropertyCollection with a simple GetProperty/SetProperty interface which would also handle AD's multivalue properties (like telephone numbers).

HTH

good stuff. i should be set. what I'm writing first is id which has only one value. so i guess just propertyname not [name][0].

thanks
Mike

This question has already been answered. Start a new discussion instead.