This one took me a little big of digging around for because the typical scenario for updating a multi-valued AD property is that a SysAdmin is adding a new email address to a list of email addresses in some property i.e. an Append Operation.
Whereas, what I wanted to do was overwrite one of the values in a multivalued property with an updated value i.e. an Update operation.
First thing you need to know is to use PutEx instead of Put when updating Multi-valued properties. Most simple examples on the Greater Google are about updating single-valued properties – integers or strings or whatever. These are updated using Put. MultiValued properties use PutEx.
Second thing is that you need to use the methods for the correct AD Provider and not to mix them up. Where you are using PutEx, then you commit that change to the actual AD database server using SetInfo() instead of CommitChanges(). I’ll get some more detail on that in here before long.
Next thing you need to realise is that the type of a MultiValued AD property in .NET is PropertyValueCollection, but that the PutEx method takes an Array Of Object (i.e. Object) as its parameter. You have to convert from PropertyValueCollection to Array. Fortunately that’s easy.
Finally, and obviously, you need to make sure that the account you are using to bind to Active Directory has Write Privileges to the entry you’re trying to update, otherwise you will get AD’s equivalent of the Blue Screen Of Death, ‘General Access Denied Error’.
To get started, here’s a great page on updating a MuliValued AD property with an Append from The Scripting Guy on TechNet. Digest this and you’ll know most of what you need to know.
Now, here’s how I did my Update operation on the Multivalued property. Probably the code is a bit clunky but it works and we can refine it a bit later. Hopefully the comments in the code provide enough explanation.
The objective is to search for the key ‘Fruit’ in the MultiValued property ‘keywords’ and update its value from ‘Banana’ to ‘Kumquat’
# The account Place\myaccount must have write privs to the LDAP Path specified.
$entry = new-object DirectoryServices.DirectoryEntry (“LDAP://MyLDAPServer/dc=place, dc=room, dc=net”, “place\myaccount”, “mypassword”)
$keywords = $entry.Keywords
# Convert keywords propertyValueCollection to a fixed-length array
# because the DirectoryEntry update function takes an Array, not
# a PropertyValueCollection as a parameter
$length = $keywords.Count
[Array]$keywordsArray = 1..$length
# This CopyTo moves the propertyValueCollection to an array.
# Search for ‘Fruit’ entry in keywords
$foundKey = $false
for($i=0; $i -lt $keywordsArray.Length; $i++)
$keyword = $keywordsArray[$i]
$foundKey = $true
# Retain index of Fruit property so it can be updated below
$fruitIdx = $i
#Check if we found Fruit Entry
if ($foundFruit -eq $false)
throw (“Did not find Fruit keyword in Active Directory object”)
# Extract Fruit Value from KeywordValue pair
# Fruit entry is “Fruit:
$fruitParts = $keyword.Split(“:”)
Write-Debug “Fruit is $fruitParts”
# Change “Fruit” key. Update the value to ‘Kumquat’
$newFruitEntry = $fruitParts + “Kumquat”
Write-Debug “Updated keyword entry is $newFruitEntry”
$keywordsArray[$FruitIdx] = $newFruitKey
# Update DirectoryEntry
# PutEx, instead of Put required for multivalued AD entries such as keyword
# First parameter denotes type of PutEx i.e. Append, Update or Delete In our case its an Update.
$ADS_PROPERTY_UPDATE = 2
$entry.PutEx($ADS_PROPERTY_UPDATE, “Keywords”, $keywordsArray)
Write-Debug “committing AD Change…”
# Commit to AD database on server