Sunday, August 7, 2011

Powershell script for bulk adsiedits

Active Directory can be a great place to keep information on your users. Email addresses, departments, full name, phone numbers, and more can be stored in AD and because it's integrated in your user provisioning process (everyone needs a logon) it makes for a logical spot to keep user information. You can even use custom attributes (we use the extensionAttributes for this) to add data that is custom to your organization.

And once you start using this infrastructure to store user data, you will quickly find a need to do bulk changes to this infrastructure (for example when your Accounting Department decides to change their name to the Finance Department, or you get a new CEO and he decides to turn your organizational tree upside down).

ADSIEDIT won't cut it for big bulk updates. Try this script instead.

To run this script you'll need a special .csv file. In the first column you'll want to place the adsi object that you want to match. So, for example, say you have a list of usernames and you wan't to change their email address from user1@domain.net to user1@domain.com. The match address will be their SAM Account Name and the second field will be their new email address. So the text file will look like this:

user1,user1@domain.com
user2,user2@domain.com
user3,user3@domain.com
...

You should NOT include header information in this file. This will get defined when the program is run.

Save the .csv file to a known location and run the script. It will prompt you for the location of the .csv file that you just saved and then ask you for the header information. This is the name of the AD objects that match with your columns. So for our example we would enter:

sAMAccountName,mail

This tells the script to go through AD and find the sAMAccountName for all the objects. If it matches with a value in column1 it then changes the "mail" object to the value in column 2.

That's it. Bulk adsi updates for every value in your .txt!

Let me know what you think and what you see in this script that can be improved.


----adsibulkedit.ps1

# import text file that contains a first column of a property to match on and a the second column is the property to change
# so if you have a .csv file and the first column is the mail and the second column is department you could then bulk change a bunch of users
# based on email address to new departments

$filename = Read-Host "Enter location for the config file"
$fileHeaders = Read-Host "Please enter headers (format is: column1label,column2label)"
$x = $fileHeaders.split(",")
$column1 = $x[0]
$column2 = $x[1]
$configfile = Import-Csv $filename -Header $column1,$column2


$strFilter = "(&(objectCategory=User))"

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"

$colProplist = $column1, $column2

foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}

$colResults = $objSearcher.FindAll()


foreach ($objResult in $colResults)
{
$objItem = $objResult.Properties
# make sure column is lowercase for fair comparison
# This is a hack. Tell me if you know a better way
$column1 = $column1.toLower()
if ( $objItem.$column1 )
{
$attribMatch = $objItem.$column1[0]
foreach ( $row in $configfile )
{
$column1value = $row.$column1
$column2value = $row.$column2
if ( $attribMatch -eq $column1value )
{
$objUser = [ADSI]$objResult.Path
$objUser.put($column2,$column2value)
$objUser.SetInfo()
Write-Host "$column1value set to $column2value"
}
}
}
}