How Can I Use Windows PowerShell to Get a List of All My Computers?

How Can I Use Windows PowerShell to Get a List of All My Computers?

  • Comments 15
  • Likes
Hey, Scripting Guy! Question

Using Windows PowerShell, how can I retrieve a list of all the computer accounts in my domain?

-- TE

SpacerHey, Scripting Guy! AnswerScript Center

Hey, TE. You know, several years ago the Scripting Guy who writes this column was playing basketball with one of his brothers. Because there were a total of 5 people at the park they had to play 2-on-2, with one person forced to sit out. After a short while a sixth person showed up and asked if he could play. He was a little guy, very quiet and unassuming, but for some reason the Scripting Guy who writes this column took one look at him and thought, “I bet he’s good.”

“I’ll guard the new guy,” said the Scripting Brother.

“I don’t know,” said the Scripting Guy who writes this column. “Maybe we should play a zone or something.”

“No,” said the Scripting Brother. “I want to guard him.”

So how did it go? Let’s put it this way: the Scripting Brother now knows, better than anyone, what the old saying about being careful what you wish for really means. As it turned out, the newcomer may very well have been the best basketball player in the history of the world. He drove past the Scripting Brother for easy lay-ins. He soared over the Scripting Brother to grab rebounds or bury jump shots. He completely and totally dominated both the game and the Scripting Brother.

About halfway through the game the Scripting Brother turned to the Scripting Guy who writes this column and said, “Do you want to switch guys?”

“No thanks,” said the Scripting Guy who writes this column, who was guarding a guy that probably hadn’t touched the ball more than 2 or 3 times the entire game. “I’m fine.”

Now, admittedly, writing a script that retrieves a list of computer accounts from Active Directory isn’t quite as difficult as guarding an unguardable player in basketball. Nevertheless, we just wanted you to know what you’re getting yourself into, TE. Remember, you asked for this:

$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}

The truth is, this script is nowhere near as bad as it looks; the problem is that it looks pretty darn intimidating. But that’s OK; after all, it is our job to try and explain how things like this work.

With an emphasis on the word try, of course.

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.

In the meantime, though, we’re off to play some basketball. Hmmm, there’s a quiet, unassuming little guy over there; we’ll guard him. And no, we’re not worried: don’t they always say that you never have to be careful what you wish for, because things always turn out great?

Or something like that anyway. We’ll ask the Scripting Brother the next time we see him.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • What are the other properties of that object? I see that you have called back $objComputer.name, what are the others? Or, how do you find out?

  • This works great except I can't figure out how to sort the output.  How would I get this to display the computers in alphabetical order?

  • GD:

    you can do this get-member -i $objComputer

    this will display the members of that object. the thing to keep in mind is how it handles collections. you can do it two different ways, as i've shown above, which if run against a collection, will show the members of the collection class, if you run it like this

    $objComputer | get-member

    it will return the members of the object in the collection , basically the same as doing this

    get-member -i $objComputer[0]

    Confuddled:

    thats an easy one, use sort :)

    $objCollection | sort <property name>

    If you have questions stop by the technet forums

    social.technet.microsoft.com/.../threads

  • It would be nice to sort the output by name.

  • You can just type in new view/ domain in CMD prompt. And it'll list them LOL

  • It's net view /domain :p

  • Howto use this to shutdown all *WORKSTATIONS* computers in the domain?

    This will give me all *computers* (including *SERVERS*) in the domain except that one, the script is running on (the PDC):

    foreach ($objResult in $colResults){$objComputer = $objResult.Properties; $objComputer.name|where {$objcomputer.name -ne $env:computername}}

    changing the final "}}" to something like "}|stop-computer -comp $objcomputer.name}" doesn't work. :-(

    Regards, Rudi.

  • @Rudi

    That is too easy ->

    ([adsisearcher]'objectCategory=computer').FindAll() |

           ?{$_.Properties['name'] -notlike $env:computername} |

           %{stop-computer $_.Properties['name'] -whatif}

    One line - No muss! No fuss!

  • Hi.

    Thanks a lot for that really cool one-liner!!

    To get this work more global, I'd like to distinguish WORKSTATIONs from SERVERs. Using google, I could find, that the computer.primarygroupid for DOMAINCONTROLLERS is 516, for all other computers (SERVER + WS) it's 515.

    Any other trick to tell, if the COMPUTER is running a SERVER-OS, beside investigating "computer.operatingSystem" ?

    Thanks, Rudi.

    (for my syntax questions I'll post separately)

  • ([adsisearcher]'(&(objectCategory=computer)(!operatingSystem=*server*))').FindAll()

    You should post all quesrions here: social.technet.microsoft.com/.../ITCG

  • Would you provide an example of getting computer list from another domain?

  • Is there a way to find computers that are currently logged in to your domain?

  • Why do this: $colResults = $objSearcher.FindAll() , followed by a foreach in $colResults
    Is there not the danger that the returned searchset can be too large to fit in memory?

    Why not enumerate directly: foreach in $objSearcher.FindAll()

  • thanks

  • I have seen this same script but instead of using system.Directoryservices the person used system32. What's the difference?