Pular para o conteúdo principal

PowerShell script for getting Active Directory information

PowerShell script for getting Active Directory information: "

For a work project, I needed to compare Active Directory actual information to what was present in our ERP system, as well as match that with information about the user’s Exchange 2003 mailbox.


I wrote a “down and dirty” PowerShell script to extract a number of fields from Active Directory and write the extracted information into a CSV file. My overall plan was to compare the three data sets — the Active Directory information, the Exchange mailbox information, and the ERP information — using Excel, while making sure there was information in all three data sets that would link the data sets to each other.


Here is more information about the project, followed by the PowerShell script I wrote.


Project details


Our reasons for this project:



  • The organization has 16,000 Exchange mailboxes, and we wanted to ensure that only users who should have mailboxes do.

  • We also wanted to ensure that Active Directory accounts for departed employees are inactive and are marked for removal.


These were the project challenges:



  • In a separate report, I had to use WMI to gather Exchange mailbox information since Exchange 2003 doesn’t include PowerShell.

  • The organization has more than 600,000 user accounts in Active Directory, most of which are valid; only about 20,000 of these accounts are employees, while the rest are customers. However, in some cases, the customers were also temporary employees, so there was a need to search the entire Active Directory database for potential employee accounts.


A look at the PowerShell script


Notes: This PowerShell script was intended for one-time use and that creates a very different development environment, at least to me. I was going for immediate functionality rather than elegance (I am not a programmer), which is why I consider this a “down and dirty” PowerShell script.


I’ll take a line-by-line (or, in some cases, a section-by-section) look at what this PowerShell script does and explain my thinking.


# Start of script

I needed to clear the screen before script execution to make sure there was no clutter that would confuse me when I looked at display results.


Cls

I added a processing loop to break down the Active Directory information into usable chunks. Prior to adding this loop, my script crashed because the machine on which I was running it ran out of memory trying to handle more than 600,000 records at once. Each item in the “targetou” section is an Active Directory organizational unit. Immediately below, you will see a line that outputs to the screen that OU is currently being processed. By displaying information at run-time, I know exactly where I am in a process.


foreach ($targetou in 'A','B','C','D','E','F','G','GUESTACCOUNTS','H','I','J','K','L','CONTRACTOR','M','N','O','P','Q','R','S','T',','U','V','W','X','Y','Z')
{
'Processing information for OU $targetou'

The $targetou variable above is the lowest point in the Active Directory hierarchy at which I worked. The $domainrootpath variable builds the full LDAP string to the OU against which the script was to run for each iteration.


$DomainRootPath='LDAP://OU='+$targetou+',OU=ORGUSER,DC=contoso,DC=com'

The next several lines create and populate an Active Directory searcher object in PowerShell.


$adsearch = New-Object DirectoryServices.DirectoryAdsearch([adsi]$DomainRootPath)

I limited the kinds of objects that would be returned. The line below limits results to user objects.


$adsearch.filter = '(objectclass=user)'

The PropertiesToLoad items below were necessary for the reporting task I had ahead of me. These lines modify the behavior of the Active Directory search by forcing it to return only what is specified rather than returning everything. Because of the size of the data set, I needed to limit the returned data to only what was essential.


$adsearch.PropertiesToLoad.AddRange(@('name'))
$adsearch.PropertiesToLoad.AddRange(@('lastLogon'))
$adsearch.PropertiesToLoad.AddRange(@('givenName'))
$adsearch.PropertiesToLoad.AddRange(@('SN'))
$adsearch.PropertiesToLoad.AddRange(@('DisplayName'))
$adsearch.PropertiesToLoad.AddRange(@('extensionAttribute1'))
$adsearch.PropertiesToLoad.AddRange(@('extensionAttribute2'))
$adsearch.PropertiesToLoad.AddRange(@('comment'))
$adsearch.PropertiesToLoad.AddRange(@('title'))
$adsearch.PropertiesToLoad.AddRange(@('mail'))
$adsearch.PropertiesToLoad.AddRange(@('userAccountControl'))
$adsearch.Container

This line executes the search based on the parameters specified above. For each iteration of the foreach loop, Active Directory will search the organizational unit for that loop and return all of the attributes specified above for each user account. The results of the execution will be stored in the variable named users. Unfortunately, as it exists, the information from this array can’t be simply written to a CSV file since that CSV file would contain only the Active Directory object name and an entry called “System.DirectoryServices.ResultPropertyCollection.” I needed to expand out and capture the individual Active Directory elements, which I do later in the script.


$users = $adsearch.findall()

As the script was running, I wanted to know how many objects were returned from each loop iteration, so I added the line below to show how many user accounts were being handled.


$users.Count

I initialized an array variable into which I’d write the individual Active Directory elements we wanted to capture.


$report = @()

I started another loop that executes for each Active Directory account for which we wanted to capture information.


foreach ($objResult in $users)
{

I needed to create a variable that houses the properties for an individual record. (There are other ways to do this, but I like to break things down to make them more readable.)


$objItem = $objResult.Properties

I created a new temporary object into which to write the various Active Directory attributes for this single record being processed in this processing iteration (remember, this is repeated for each record returned from Active Directory).


$temp = New-Object PSObject

For each individual Active Directory property that was returned from the Active Directory searcher, I added a named property to the temp variable for this loop iteration. Basically, this breaks out the single Active Directory record for a user into its individual components, such as name, title, email address, and so forth. (Case-sensitivity matters in this section.)


$temp | Add-Member NoteProperty name $($objitem.name)
$temp | Add-Member NoteProperty title $($objitem.title)
$temp | Add-Member NoteProperty mail $($objitem.mail)
$temp | Add-Member NoteProperty displayname $($objitem.displayname)
$temp | Add-Member NoteProperty extensionAttribute1 $($objitem.extensionattribute1)
$temp | Add-Member NoteProperty extensionAttribute2 $($objitem.extensionattribute2)
$temp | Add-Member NoteProperty givenname $($objitem.givenname)
$temp | Add-Member NoteProperty sn $($objitem.sn)
$temp | Add-Member NoteProperty useraccountcontrol $($objitem.useraccountcontrol)

I added the results of this individual record to the primary array into which we’re capturing the full results from the search for later export to CSV.


$report += $temp
}

This line creates the name of the file that will be written. I created a new file for each organizational unit processed.


$csvfile='AD-'+$targetou+'.csv'

The line writes the entire file to disk and then notifies the user that processing for this OU has completed.


$report | export-csv -notypeinformation $csvfile
'Wrote file for $targetou'
}

Summary


For my purposes, this PowerShell script captured exactly the information that I needed, and I was able to complete my comparison task. If you know of a more elegant way to get this information, please post it in the discussion.


More PowerShell tips and tricks



Keep up with Scott Lowe’s posts on TechRepublic






"

Comentários

Postagens mais visitadas deste blog

Favigen, Favicon Generator

Favigen, Favicon Generator : " Favicons are small icons that help identify websites. They are used as a visual representation of a website both in the web browser and at many online services. The three most prominent locations of favicons are the browser’s address bar, the tabbar and the bookmarks folder. Many webmasters like to create custom favicons to add that custom identifier to their website. Favicons can be created in many image and icon editors, but also online. Favigen is a straightforward favicon generator that can turn an image into a favicon. All that it takes is to pick an image from the local hard drive first, select the dimensions of the favicon and click the submit button to make the service generate the favicon. Favigen supports several image formats, including jpg and png, and it does not seem to have size restrictions either. Available image dimensions range are 16×16, 32×32 and 64×64. The generated favicon is displayed directly on the page. A click on do...

A simple rsync script to back up your home directory

A simple rsync script to back up your home directory : " Backing up important data is obviously something we should all do. Unfortunately, it is not always easy to make it happen. We get lazy; we do not have the additional hardware for a backup server; it takes a long time and a lot of CDs to back up to optical media; we do not trust online backup services; backup schemes are difficult to set up and use — any of dozens of reasons can stand in our way. Still, we know we should be backing up our important data. Modern open source Unix-like operating systems offer a plethora of options for incredibly simple, effective backup schemes, however. If the problem is figuring out how to set one up, a simple rsync solution may be exactly what you need. The rsync utility is used to synchronize files between two systems. It does so by way of incremental copies, only copying from the source to the destination what has not already been copied there, saving time, network bandwidth, and syst...

Google Wave now open to the public: faster, Robots and Gadgets aplenty!

Google Wave now open to the public: faster, Robots and Gadgets aplenty! : " Filed under: Internet , Google If you somehow missed it, Google Wave is now a bonafide Labs project: rather than being an invite-only alpha, it's now a public beta test! If you don't already have an account, just head on over to Wave and use your regular Google login details. If you've not seen any of the Google Wave introductory videos , you should check them out -- they explain the whole thing a lot more succinctly than I ever could. Wave has also been enabled for Google Apps domains -- businesses could convert their internal communication to Waves today! Leading up to this public release there have a lot of changes. It's by no means finished, but Google Wave is now a lot faster . It's also more intuitive -- more useful -- and given the large number of Robots and Gadgets now reaching prime-time readiness, it feels like the mass adoption of Wave is imminent. Also, if you're an ol...