Getting computer names from AD using Powershell

From Svendsen Tech Powershell Wiki
Jump to: navigation, search

Often as a Windows system administrator, you will want to get a list of computer/host names from (an OU in) Active Directory. Here are a few ways of doing it with PowerShell, using System.DirectoryServices.DirectorySearcher ([adsisearcher]) with an LDAP query, Get-ADComputer from the Microsoft ActiveDirectory module cmdlets and Get-QADComputer from Quest ActiveRoles.

These MS AD cmdlets that Get-ADComputer and Get-ADObject are part of are installed as a feature under the category "Remote Server Administration Tools" (RSAT) from Server Manager on Windows Server 2008 R2 and Windows 7. There's more information about this here and here.

See this article for getting usernames.


Using Get-ADComputer

Firstly, unless you're on PSv3 or later (autoloads modules when you use cmdlets), you need to import the ActiveDirectory module after having installed it as a feature (under RSAT in Server Manager -> Features -> Add feature -> Remote Server Administration Tools):

PS C:\prog\PowerShell> Import-Module ActiveDirectory
PS C:\prog\PowerShell>

Also, don't forget to look at Get-Help Get-ADComputer -Full!

To just dump every single computer in a domain, and possibly redirect to a file by adding " > computers.txt", you can do it like this:

PS C:\prog\PowerShell> Get-ADComputer -Filter 'ObjectClass -eq "Computer"' | Select -Expand DNSHostName

Technically, that filter is (bloody well should be) redundant. You can also use -like instead of -eq. I'm having some trouble with wildcards in combination with text, though (such as in 'ObjectClass -like "*ompute*"').

You can also redirect to a file, and specify encoding, by piping to Set-Content rather than using the redirection operator ">", which does the same thing as Out-File. When working with text/strings, they will work equivalently, and since we're using Select-Object with the parameter -ExpandProperty ("-Exp" in the examples), we get strings. There's a lot more to be said about this, but it does not belong in this article.

Getting Just The Host Name

Above I selected the property "DNSHostName". If you use the property "Name" instead, you will get just the host name:

PS C:\prog\PowerShell> Get-ADComputer -Filter '*' | Select -Expand Name

I also used a different filter here. Basically, when you use the Get-ADComputer cmdlet, there should be built-in filtering that targets computer objects, so you can use any property and a wildcard match with "-like '*'" or similar. I experimented with just a wildcard ("*") to target anything, and it seems to work as intended.

Getting Server Or Client Operating Systems Only

To get server operating systems only, I currently don't know of any (much) better way than filtering on the "OperatingSystem" text containing "Windows Server". You can also use a script block for the filter, which helps avoid nested quoting, and can be done like this:

PS C:\> Get-ADComputer -Filter { OperatingSystem -Like '*Windows Server*' } -Properties OperatingSystem | 
>> Select Name, OperatingSystem | Format-Table -AutoSize

Name          OperatingSystem
----          ---------------
2008R2ESXI2   Windows Server 2008 R2 Standard
2008R2ESXI    Windows Server 2008 R2 Standard
SRV2003R2ESXI Windows Server 2003
SERVER2003    Windows Server 2003
SERVER2008    Windows Serverr 2008 Standard
SERVER2012RC  Windows Server 2012 Release Candidate Datacenter

PS C:\>

As we can see, this works for Server 2003 through Server 2012 versions of Windows Server operating systems.

To do the opposite, and only get client operating systems, you can use -NotLike instead of -Like:

PS C:\> Get-ADComputer -Filter { OperatingSystem -NotLike '*Windows Server*' } -Properties OperatingSystem | 
>> Select Name, OperatingSystem | Format-Table -AutoSize

Name        OperatingSystem
----        ---------------
SIEMENS     Windows XP Professional
WIN7ESXI    Windows 7 Professional
WINXPESXI   Windows XP Professional
WIN2K       Windows 2000 Professional
VISTA64ESXI Windows VistaT Ultimate
XPTANKET    Windows XP Professional
esxi        unknown
WINXPSSD    Windows XP Professional
VMWAREWIN7  Windows 7 Professional
SS-WIN7     Windows 7 Professional
WIN8VM      Windows 8 Pro

PS C:\>

Getting Service Pack Version

PS C:\> Get-ADComputer -Filter 'name -eq "2008r2esxi"' -Properties OperatingSystemServicePack
   | select Name, OperatingSystemServicePack | ft -AutoSize

Name       OperatingSystemServicePack
----       --------------------------
2008R2ESXI Service Pack 1

How to List All AD Computer Properties

Get any computer object from AD and pipe it to Get-Member (if there are multiple, Get-Member is smart enough to only show the info once).

PS C:\> Get-ADComputer -Filter * -Properties * | Get-Member | ft -AutoSize

   TypeName: Microsoft.ActiveDirectory.Management.ADComputer

Name                                 MemberType            Definition
----                                 ----------            ----------
Contains                             Method                bool Contains(string propertyName)
Equals                               Method                bool Equals(System.Object obj)
GetEnumerator                        Method                System.Collections.IDictionaryEnumerator GetEnumerator()
GetHashCode                          Method                int GetHashCode()
GetType                              Method                type GetType()
ToString                             Method                string ToString()
Item                                 ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
AccountExpirationDate                Property              System.DateTime AccountExpirationDate {get;set;}
accountExpires                       Property              System.Int64 accountExpires {get;set;}
AccountLockoutTime                   Property              System.DateTime AccountLockoutTime {get;set;}
AccountNotDelegated                  Property              System.Boolean AccountNotDelegated {get;set;}
AllowReversiblePasswordEncryption    Property              System.Boolean AllowReversiblePasswordEncryption {get;set;}
AuthenticationPolicy                 Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
AuthenticationPolicySilo             Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
BadLogonCount                        Property              System.Int32 BadLogonCount {get;}
CannotChangePassword                 Property              System.Boolean CannotChangePassword {get;set;}
CanonicalName                        Property              System.String CanonicalName {get;}
Certificates                         Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
CN                                   Property              System.String CN {get;}
codePage                             Property              System.Int32 codePage {get;set;}
CompoundIdentitySupported            Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
countryCode                          Property              System.Int32 countryCode {get;set;}
Created                              Property              System.DateTime Created {get;}
createTimeStamp                      Property              System.DateTime createTimeStamp {get;}
Deleted                              Property              System.Boolean Deleted {get;}
Description                          Property              System.String Description {get;set;}
DisplayName                          Property              System.String DisplayName {get;set;}
DistinguishedName                    Property              System.String DistinguishedName {get;set;}
DNSHostName                          Property              System.String DNSHostName {get;set;}
DoesNotRequirePreAuth                Property              System.Boolean DoesNotRequirePreAuth {get;set;}
dSCorePropagationData                Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
Enabled                              Property              System.Boolean Enabled {get;set;}
frsComputerReferenceBL               Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
HomedirRequired                      Property              System.Boolean HomedirRequired {get;set;}
HomePage                             Property              System.String HomePage {get;set;}
instanceType                         Property              System.Int32 instanceType {get;}
IPv4Address                          Property              System.String IPv4Address {get;}
IPv6Address                          Property              System.String IPv6Address {get;}
isCriticalSystemObject               Property              System.Boolean isCriticalSystemObject {get;set;}
isDeleted                            Property              System.Boolean isDeleted {get;}
KerberosEncryptionType               Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
LastBadPasswordAttempt               Property              System.DateTime LastBadPasswordAttempt {get;}
LastKnownParent                      Property              System.String LastKnownParent {get;}
lastLogon                            Property              System.Int64 lastLogon {get;set;}
LastLogonDate                        Property              System.DateTime LastLogonDate {get;}
lastLogonTimestamp                   Property              System.Int64 lastLogonTimestamp {get;set;}
localPolicyFlags                     Property              System.Int32 localPolicyFlags {get;set;}
Location                             Property              System.String Location {get;set;}
LockedOut                            Property              System.Boolean LockedOut {get;set;}
logonCount                           Property              System.Int32 logonCount {get;set;}
ManagedBy                            Property              System.String ManagedBy {get;set;}
MemberOf                             Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
MNSLogonAccount                      Property              System.Boolean MNSLogonAccount {get;set;}
Modified                             Property              System.DateTime Modified {get;}
modifyTimeStamp                      Property              System.DateTime modifyTimeStamp {get;}
msDS-SupportedEncryptionTypes        Property              System.Int32 msDS-SupportedEncryptionTypes {get;set;}
msDS-User-Account-Control-Computed   Property              System.Int32 msDS-User-Account-Control-Computed {get;}
Name                                 Property              System.String Name {get;}
netbootSCPBL                         Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
nTSecurityDescriptor                 Property              System.DirectoryServices.ActiveDirectorySecurity nTSecuri...
ObjectCategory                       Property              System.String ObjectCategory {get;}
ObjectClass                          Property              System.String ObjectClass {get;set;}
ObjectGUID                           Property              System.Nullable`1[[System.Guid, mscorlib, Version=
objectSid                            Property              System.Security.Principal.SecurityIdentifier objectSid {g...
OperatingSystem                      Property              System.String OperatingSystem {get;set;}
OperatingSystemHotfix                Property              System.String OperatingSystemHotfix {get;set;}
OperatingSystemServicePack           Property              System.String OperatingSystemServicePack {get;set;}
OperatingSystemVersion               Property              System.String OperatingSystemVersion {get;set;}
PasswordExpired                      Property              System.Boolean PasswordExpired {get;set;}
PasswordLastSet                      Property              System.DateTime PasswordLastSet {get;set;}
PasswordNeverExpires                 Property              System.Boolean PasswordNeverExpires {get;set;}
PasswordNotRequired                  Property              System.Boolean PasswordNotRequired {get;set;}
PrimaryGroup                         Property              System.String PrimaryGroup {get;}
primaryGroupID                       Property              System.Int32 primaryGroupID {get;set;}
PrincipalsAllowedToDelegateToAccount Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
ProtectedFromAccidentalDeletion      Property              System.Boolean ProtectedFromAccidentalDeletion {get;set;}
pwdLastSet                           Property              System.Int64 pwdLastSet {get;set;}
rIDSetReferences                     Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
SamAccountName                       Property              System.String SamAccountName {get;set;}
sAMAccountType                       Property              System.Int32 sAMAccountType {get;set;}
sDRightsEffective                    Property              System.Int32 sDRightsEffective {get;}
serverReferenceBL                    Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
ServiceAccount                       Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
servicePrincipalName                 Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
ServicePrincipalNames                Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
SID                                  Property              System.Security.Principal.SecurityIdentifier SID {get;set;}
SIDHistory                           Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
TrustedForDelegation                 Property              System.Boolean TrustedForDelegation {get;set;}
TrustedToAuthForDelegation           Property              System.Boolean TrustedToAuthForDelegation {get;set;}
UseDESKeyOnly                        Property              System.Boolean UseDESKeyOnly {get;set;}
userAccountControl                   Property              System.Int32 userAccountControl {get;set;}
userCertificate                      Property              Microsoft.ActiveDirectory.Management.ADPropertyValueColle...
UserPrincipalName                    Property              System.String UserPrincipalName {get;set;}
uSNChanged                           Property              System.Int64 uSNChanged {get;}
uSNCreated                           Property              System.Int64 uSNCreated {get;}
whenChanged                          Property              System.DateTime whenChanged {get;}
whenCreated                          Property              System.DateTime whenCreated {get;}

Targeting A Specific OU

Here I target the OU "svendsen.local/Hjemme/Clients" using the -SearchBase parameter and the LDAP distinguished name for this OU.

PS C:\> Get-ADComputer -SearchBase 'OU=Clients,OU=Hjemme,dc=svendsen,dc=local' -Filter '*' | Select -Exp Name

This OU:


Using An LDAP Query

Using an LDAP query effectively similar to the filter in the first example, you can do something like this:

PS C:\prog\PowerShell> Get-ADComputer -LDAPFilter '(objectClass=Computer)' | Select -Expand Name

Using An LDAP Query And Get-ADObject

You can use the same filter with Get-ADObject:

PS C:\prog\PowerShell> Get-ADObject -LDAPFilter '(objectClass=Computer)' | Select -Expand Name

Filtering Using Wildcards And Where-Object

Here I filter on computer names that start with "2008":

PS C:\prog\PowerShell> Get-ADComputer -Filter 'SamAccountName -like "2008*"' | Select -Exp Name

And here I filter on computer names that contain "2008":

PS C:\prog\PowerShell> Get-ADComputer -Filter 'SamAccountName -like "*2008*"' | Select -Exp Name

Of course you can also filter in the pipeline using PowerShell's Where-Object/Where, but it will be less efficient on large queries:

PS C:\prog\PowerShell> Get-ADComputer -Filter * | Where { $_.Name -imatch '2008' } | Select -Exp Name

Using DirectorySearcher/AdsiSearcher

If this is the absolute best way of doing this, I do not know, but it seems quite likely that it's no crime against humanity given my experimentation and inspection of the (computer) objects returned by DirectoryServices.DirectorySearcher.

Here's the output from my home lab's AD (these indeed are all the computers in the Active Directory):

PS C:\prog\PowerShell> .\Get-Computers-DS.ps1

Basically with DirectoryServices.DirectorySearcher, the real magic is in the LDAP query, and you might have to inspect returned objects to see what their properties are. The LDAP query is specified via the Filter property of the directory searcher object, and in this case it is "(objectClass=Computer)".

Also be aware that the property you index is case-sensitive, and that they're all listed as lower-case when you look at the returned System.DirectoryServices.ResultPropertyCollection object.

Here is a ready-made script that'll just dump every single computer from the AD of the first available domain controller, using Windows' method for detecting domain controllers:

#Set-StrictMode -Version Latest
#$ErrorActionPreference = 'Stop'

$DirSearcher = New-Object System.DirectoryServices.DirectorySearcher([adsi]'')
$DirSearcher.Filter = '(objectClass=Computer)'

# These properties are part of a DirectoryServices.ResultPropertyCollection
# NB! These properties need to be all lowercase!
$DirSearcher.FindAll().GetEnumerator() | ForEach-Object { $ }

I should also mention that there's a type accelerator in PowerShell v2 (I don't know about v1.x), which allows you to skip a few steps like this (notice the two quotes after the type accelerator):

PS C:\> $DirSearcher = [adsisearcher]''
PS C:\>

Targeting A Specific OU With ADSI/LDAP/DirectorySearcher

To target a specific OU/container, change the following line in the script above (this example is valid in my home lab):

$DirSearcher = New-Object DirectoryServices.DirectorySearcher([adsi]'LDAP://OU=Clients,OU=Hjemme,DC=svendsen,DC=local')

So here I prepended "LDAP://" to the distinguished name of the OU, enclosed it in a string and cast it to an ADSI object, which was then used to to create a System.DirectoryServices.DirectorySearcher object. This targets the OU svendsen.local/Hjemme/Clients. Using "System." first when declaring the object type is optional.

If you were to use the [adsisearcher] type accelerator, it would look like this:

$DirSearcher = [adsisearcher][adsi]'LDAP://OU=Clients,OU=Hjemme,DC=svendsen,DC=local'

Parsing dsquery.exe Output

If, for some reason, you're stuck parsing dsquery.exe output, here's just a random example of me retrieving server names for everything under a certain OU (made a bit anonymous: OU=Servere,OU=Boxes,dc=ad,dc=company,dc=no /

PS C:\> $dsq = dsquery computer -limit 0

PS C:\> $dsq[0]
"SERVERDCNAME,OU=Domain Controllers,DC=ad,DC=company,DC=no"

PS C:\> $SrvStrings = $dsq | where { $_ -like '*OU=Servere,OU=Boxes,dc=ad,dc=company,dc=no*' }

PS C:\> $SrvStrings[0]

PS C:\> $Servers = $SrvStrings | %{ if ($_ -match '^"CN=([^,]+)') { $matches[1] } }

PS C:\> $Servers[0]

PS C:\>

Using Quest ActiveRoles Get-QADComputer

This example, and the script below, uses Get-QADComputer from Quest ActiveRoles - a very handy and seemingly mature set of cmdlets for working with Active Directory. They are free - and also work against ADs running on Server 2003 without Active Directory Web Services.

PS C:\powershell> Get-QADComputer -SearchRoot -SizeLimit 0 | %{ $_.Name }
PS C:\powershell> Get-QADComputer -SearchRoot -SizeLimit 0 | %{ $_.Name } > foo.txt
PS C:\powershell> (Get-Content .\foo.txt).Count
PS C:\powershell> (Get-Content .\foo.txt)[1,-1]

Rather than " | %{ $_.Name }", you can probably more conventionally use " | Select-Object -ExpandProperty Name". You can also use " | Out-File foo.txt" instead of " > foo.txt" - or Add/Set-Content. (Do we love or hate choices? They sort of suck when documenting.)

Random Get-QADComputer Sample

This script will get some data from AD and redirect it to a file. Easily adapted to other needs. This will retrieve the fields Name, OSName, OSVersion, OSServicePack and LastLogonTimeStamp. See the sample output below for what it looks like. I find sorting on LastLogonTimeStamp useful (read about it here and here). I use this script to manually inspect and just remove "old" computers if I'm going to run a command against multiple online computers, for instance.

More conventionally you will probably want to export to CSV. Check Get-Help Export-Csv -Full. Basically, you'd replace the Format-Table and Out-File with something like:

Get-QADComputer ... bla bla |
Export-Csv -Encoding UTF8 -Delimiter ";" -NoTypeInfo computers.csv

A little ninja tip, especially if you're preparing CSV reports for non-technical people to read, is to use a semicolon as the delimiter rather than a comma as this makes it load properly divided into columns automatically, in Excel, whereas with a comma I have to import it manually through the wizard. Explaining how to do this (possibly with 3-4 different versions of Excel) is inconvenient, and a lot of people just won't do it; they'll just double-click the CSV file and assume what they're looking at is a proper representation of the data, even if it's all in one column, with quotes intact...


Sample Output

PS C:\powershell> .\get-all-ad-computers.ps1

cmdlet get-all-ad-computers.ps1 at command pipeline position 1
Supply values for the following parameters:
OutputFile: test.txt
Running Get-QADComputer...
Start time:  05/19/2011 23:36:14
End time:    05/19/2011 23:36:28
Output file: test.txt
PS C:\powershell> notepad .\test.txt
PS C:\powershell> type .\test.txt | Select-Object -first 10

Name            OSName                  OSVersion  OSServicePack          lastLogonTimestamp
----            ------                  ---------  -------------          ------------------
comp1           Windows XP Professional 5.1 (2600) Service Pack 2         17.03.2010 03:07:14
comp2           Windows XP Professional 5.1 (2600) Service Pack 2         18.03.2010 08:04:52
comp3           Windows XP Professional 5.1 (2600) Service Pack 3         18.03.2010 12:27:59
comp4           Windows XP Professional 5.1 (2600) Service Pack 3         18.03.2010 12:35:31
comp5           Windows XP Professional 5.1 (2600) Service Pack 3         18.03.2010 14:07:31
comp6           Windows XP Professional 5.1 (2600) Service Pack 3         19.03.2010 11:46:23
comp7           Windows XP Professional 5.1 (2600) Service Pack 3         20.03.2010 19:50:29

Getting Just The Computer Names From That Output

I figure you might want to get just the computer names from that output, and of course you can just run a query where you pipe Get-QADComputer to Select-Object -ExpandProperty Name, but I'll throw in a little example of getting the first "word" (non-whitespace characters in sequence) on a line. In this case you will have to remove the headers manually with notepad or another editor (or Get-Content and Select-Object -First/-Last/-Skip if you like).

Using Split

Read more about the PowerShell split operator here.

PS E:\temp> (gc .\computers.txt)[0,-1]
comp1           Windows XP Professional 5.1 (2600) Service Pack 2         17.03.2010 03:07:14
comp7           Windows XP Professional 5.1 (2600) Service Pack 3         20.03.2010 19:50:29

PS E:\temp> gc .\computers.txt | %{ ($_ -split '\s+')[0] }
Using A Regular Expression

Read more about PowerShell regular expressions here.

PS E:\temp> (gc .\computers.txt)[0,-1]
comp1           Windows XP Professional 5.1 (2600) Service Pack 2         17.03.2010 03:07:14
comp7           Windows XP Professional 5.1 (2600) Service Pack 3         20.03.2010 19:50:29

PS E:\temp> gc .\computers.txt | %{ if ($_ -match '^(\S+)') { $matches[1] } }

Script Code

param([Parameter(Mandatory=$true)][string] $OutputFile)

$StartTime = Get-Date

# Check that the Quest.ActiveRoles.ADManagement snapin is available
if (!(Get-PSSnapin Quest.ActiveRoles.ADManagement -registered -ErrorAction SilentlyContinue)) {
    'You need the Quest ActiveRoles AD Management Powershell snapin to use this script'
    'Please install and register this snapin. Exiting...'
    exit 0

# Add the snapin and don't display an error if it's already added.
# If it's not registered, this will be handled above, so this should succeed.
Add-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue

'Running Get-QADComputer...'

Get-QADComputer -SizeLimit 0 -IncludedProperties LastLogonTimeStamp | 
  Select-Object Name, OSName, OSVersion, OSServicePack, LastLogonTimeStamp |
  #Where-Object { ($_.OSVersion -match '^5\.1') } | # Filter on XP/2003
  Sort-Object @{Expression={$_.LastLogonTimeStamp};Ascending=$true} |
  #Export-Csv -Encoding UTF8 -Delimiter ";" -NoTypeInfo computers.csv
  Format-Table -AutoSize -Property Name, OSName, OSVersion, OSServicePack, LastLogonTimeStamp |
  Out-File $OutputFile

Start time:  $StartTime
End time:    $(Get-Date)
Output file: $OutputFile

Keywords: Active Directory, AD, Powershell, Exporting, CSV, LastLogonTimeStamp, LastLogon, Quest ActiveRoles cmdlets, Get-ADComputer, DirectorySearcher, LDAP query for computers

Personal tools