I said when I posted about fixing the phone numbers in your Outlook Contacts that I'd come back and do the same thing for Active Directory. Richard told people to look out for that, so no pressure to get it done then...
Using the Active Directory Services interface (ADSI) from Powershell seems to fill some people with fear. One of the books I picked up said "don't bother" use VB. I found the Mastering PowerShell in your lunch-break pages quite helpful on ADSI; and there are a bunch of tools worth investigating. I wanted to do this without creating a dependency on those, if I could.
So here are a few bits that might be useful before I dive into the code.
I've kept the same structure as I used in the Outlook Contacts version. I've kept the same function Format-number-as-E164 and I have another function which takes a user or contact object, checks to see if phone numbers are present and if they are, it calls Format-number-as-E164. This follows the same pattern as the outlook one, but is named function Format-ADPerson-as-e164 and takes an LDAP path as a parameter. The AD fields it looks at are facsimileTelephoneNumber, homePhone, ipPhone, mobile, pager, PrimaryInternationalISDNNumber , TelephoneAssistant and TelephoneNumber
Rather than show identical code for all these attributes, I've just shown one below.
function Format-ADPerson-as-e164 ($LDAPpath) { $changed=$false $Contact=[ADSI]($LDAPPath) if($contact.psbase.properties.facsimileTelephoneNumber) {$temp = Format-Number-as-E164($contact.facsimileTelephoneNumber) if ($temp -ne $contact.facsimileTelephoneNumber) {$contact.facsimileTelephoneNumber=$temp $changed=$TRUE} } if ($changed) { write-host $contact.name changed $contact.setInfo() } }
{ $changed=$false $Contact=[ADSI]($LDAPPath) if($contact.psbase.properties.facsimileTelephoneNumber) {$temp = Format-Number-as-E164($contact.facsimileTelephoneNumber) if ($temp -ne $contact.facsimileTelephoneNumber) {$contact.facsimileTelephoneNumber=$temp $changed=$TRUE} }
if ($changed) { write-host $contact.name changed $contact.setInfo() } }
Then it needs to be called for many AD users, By using [ADSI]"", and filtering to the "Person" objectClass, I selected every user and contact in my domain but you could specify a single OU or a more restrictive filter.
$searcher= New-Object directoryServices.DirectorySearcher([Adsi]"") $searcher.filter="(objectclass=person)" $searcher.findall() | forEach-Object {$_.path}
$searcher.filter="(objectclass=person)"
$searcher.findall() | forEach-Object {$_.path}
The last line is there to show which objects are going to be processed. When I'm happy that I've go the right objects and the right code
$searcher.findall() | foreach-object {Format-ADPerson-as-e164($_.path)}
Does the processing.
The code is attached for you to play with, but as I've said before, and will say in the future; any code I provide here is for example purposes. No Warranty or support is provided. You should take steps to validate any such code or yourself before running it.