How to retrieve a list of Computer Accounts from Active Directory

By Jesse Hamrick • January 10th, 2008

I've written a few posts and a couple of tutorials that discuss connecting to remote machines. For example:

In each of these articles an array is used to connect to multiple remote computers. The procedure consists of placing computer names in a text file which is then read by the "Get-Content" cmdlet which creates the array.

I've received comments and emails asking how to query Active Directory for all the computer accounts. Well, here is how we do that…

I have to give credit to where credit is due. I just downloaded "The Hey, Scripting Guy! Archive: Volume 2 (August 2004 - September 2007)" and found a PowerShell script that uses .NET and LDAP to query Active Directory for all computers. The output is just what we are looking for, the computer names. Here is the PowerShell script:

$strCategory = "computer"

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = ("(objectCategory=$strCategory)")

$colProplist = "name"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}

$colResults = $objSearcher.FindAll()

foreach ($objResult in $colResults)
    {$objComputer = $objResult.Properties; $objComputer.name}

Save the script as GetPCNames.ps1 and run it in your Domain.

Now lets create the Computers.txt file that is used by the "Get-Content" cmdlet examples on this site.

.\GetPCNames.ps1 > "C:\MyScripts\Computers.txt"

I was able to create a list of 4,000 computer names within 3 seconds, results may vary…

   
 

Here is the explanation of how the script works and who better to explain it than "The Scripting Guy!"

We start out simply enough, assigning the value computer to a variable named $strCategory. We then use this line of code to create a new instance of the .NET Framework class System.DirectoryServices.DirectoryEntry. Because we didn’t specify any additional parameters when creating this instance our object reference $objDomain will automatically connect us to the root of our Active Directory domain. Neat, huh?

 

Incidentally, here’s the line of code we were talking about:

 

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

 

After we connect to the domain we then need to create an instance of the System.DirectoryServices.DirectorySearcher class; that’s the object we’ll use to conduct our Active Directory search. After creating the object we then use these two lines of code to assign values to the DirectorySearcher SearchRoot and Filter properties:

 

$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = ("(objectCategory=$strCategory)")

 

As you probably figured out, the SearchRoot property simply tells DirectorySearcher where to begin searching. We want to search the entire domain so we set SearchRoot to the object reference $objDomain. In turn, the Filter property enables us to target a specific subset of the items found in Active Directory. Because the only thing we care about are computers, we tell the Filter property to bring back only those objects where the objectCategory attribute is equal to the variable $strCategory (which, as you recall, is equal to computer.)

 

Note. A detailed explanation of how to search Active Directory using Windows PowerShell falls way outside the scope of this little column. We will note, however, that the Filter property requires the LDAP search syntax; you can’t use the more familiar SQL-style syntax here. For more information, see the DirectorySearcher documentation on MSDN.

 

Our next step is to specify which attributes and attribute values we want our search to bring back. (If you don’t specify a so-called “property list” you’ll get back all the attributes and attribute values, which is not only more information than you need, but probably more data than you want to have clogging up your network.) These two lines of code add the name attribute to the list of property values we want back:

 

$colProplist = "name"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}

 

We should point out that property lists need to be constructed as arrays. Why do we care about that? Well, suppose we wanted to get back both the name and the cn. In that case we’d have to assign the two values to $colProplist using syntax like this:

 

$colProplist = "name", "cn"

 

And yes, that is an array: in Windows PowerShell you can create an array just by assigning multiple values (with individual values separated by commas) to a variable.

 

After we’ve created an array our next chore is to use the PropertiesToLoad method to add those properties to our DirectorySearcher. To do that we set up a For Each loop to loop through all the items in the array, adding each item to the DirectorySearcher:

 

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

 

Note. What’s that? You don’t know how to create a For Each loop in Windows PowerShell? If that’s the case, you should take a look at our Task-Based Introduction to Windows PowerShell.

 

Now, at long last, we’re ready to search Active Directory. To do that we call the FindAll() method, storing the data the search brings back in a variable named $colResults:

 

$colResults = $objSearcher.FindAll()

 

The only thing left to do now is set up a second For Each loop to loop through all the items (computers) in the collection $colResults. For each item (computer) in the collection we use this snippet of code to store the item Properties in a variable named $objComputer; we do that because, even though we asked for only the name, by default we also get back the computer’s ADsPath, something which can make our output difficult to read:

 

$objComputer = $objResult.Properties

 

If we don’t mind difficult-to-read output we could just echo back the value of $colResults and call it good:

 

$colResults

 

As soon as the computer Properties have been stashed in $objComputer we can then use this command to echo back just the computer name:

 

$objComputer.name

 

That’s going to give us output that looks something like this:

 

atl-dc-01
atl-dc-02
atl-dc-03
atl-dc-04

 

Which is exactly what we wished for in the first place.

 

Like we said, this script is a little complicated, although that’s due in part to all the $’s and curly braces and other unusual characters you have to use in a Windows PowerShell script. Complicated or not, though, we know that there’s a lot of interest in using Windows PowerShell to work with Active Directory, so we’ll see what we can do about that in the future.

 

Email This Post To A Friend Email This Post To A Friend 

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • Digg
  • Furl
  • Reddit
  • Technorati
  • YahooMyWeb

Comments

Very kewl!

By Steven Murawski on January 10th, 2008 at 12:14 pm

That is one way to do it. Another would be Get-QADComputer, which is a cmdlet supplied by Quest (for free!). Their cmdlets make working with Active Directory much, much easier, and turn your above script into “Get-QADComputer | Select-Object -Property name” for the same result.

Steven,
Thanks for the additional info. Custom cmdlets are a great feature of PowerShell. In fact, if you are savy with C# programming you can build your own cmdlets just like Quest. Here is the new developers book for PowerShell Programming

 

Leave a Comment

« Why would I want to call a function that exists in a separate script? | Home | WMI Explorer : Script-O-Matic for PowerShell »