Updated : October 01, 2015
Question : What is the fastest solution to count all the users in Active Directory domain?
Answer : To answer this question, I will compare 17 different commands in a domain with 75 000 users.
[System.GC]::WaitForPendingFinalizers() [System.GC]::Collect() Set-Location -Path 'C:\demo' Add-Type -AssemblyName System.DirectoryServices.Protocols Import-Module -Name .\S.DS.P.psd1 Add-PSSnapin -Name 'Quest.ActiveRoles.ADManagement' $searcher = [adsisearcher]'(&(objectclass=user)(objectcategory=person))' $searcher.SearchRoot = 'LDAP://DC=domain,DC=com' $searcher.PageSize = 1000 $searcher.PropertiesToLoad.AddRange(('samaccountname')) function Get-QueryResult { [CmdletBinding()] Param ( [Parameter(Mandatory=$true)] [int]$Id ) switch ($id) { 1 { ( Get-ADUser -Filter 'objectClass -eq "user" -and objectCategory -eq "person"' -SearchBase 'DC=domain,DC=com' -Properties SamAccountName).SamAccountName } 2 { ( Get-ADUser -LDAPFilter '(&(objectclass=user)(objectcategory=person))' -SearchBase 'DC=domain,DC=com' -Properties SamAccountName).SamAccountName } 3 { ( Get-ADObject -Filter 'objectCategory -eq "person" -and objectClass -eq "user"' -SearchBase 'DC=domain,DC=com' -Properties SamAccountName).SamAccountName } 4 { ( Get-ADObject -LDAPFilter '(&(objectclass=user)(objectcategory=person))' -SearchBase 'DC=domain,DC=com' -Properties SamAccountName).SamAccountName } 5 { ( Get-ADObject -LDAPFilter 'sAMAccountType=805306368' -SearchBase 'DC=domain,DC=com' -Properties SamAccountName).SamAccountName } 6 { ( Get-QADUser -SearchRoot 'DC=domain,DC=com' -DontUseDefaultIncludedProperties -IncludedProperties SamAccountName -SizeLimit 0).SamAccountName } 7 { ( $searcher.FindAll() ) } 8 { (Find-LdapObject -SearchFilter:'(&(objectclass=user)(objectcategory=person))' -SearchBase:'DC=domain,DC=com' -LdapServer:'' -PageSize 1000 -PropertiesToLoad:@('sAMAccountName')) } 9 { (Find-LdapObject -SearchFilter:'sAMAccountType=805306368' -SearchBase:'DC=domain,DC=com' -LdapServer:'' -PageSize 1000 -PropertiesToLoad:@('sAMAccountName')) } 10 { (Find-LdapObject -SearchFilter:'(&(objectclass=user)(objectcategory=person))' -SearchBase:'DC=domain,DC=com' -LdapServer:'' -PageSize 1000) } 11 { (Find-LdapObject -SearchFilter:'sAMAccountType=805306368' -SearchBase:'DC=domain,DC=com' -LdapServer:'' -PageSize 1000) } 12 { (dsquery user -o samid 'DC=domain,DC=com' -limit 0) } 13 { (dsquery * -filter '(&(objectclass=user)(objectcategory=person))' -attr samAccountName -attrsonly -limit 0) } 14 { (dsquery * -filter 'sAMAccountType=805306368' -attr samAccountName -attrsonly -limit 0) } 15 { ([regex]::match((.\AdFind.exe -b 'DC=domain,DC=com' -f '(&(objectclass=user)(objectcategory=person))' -c),'\d{5}').value) 2> $null } 16 { ([regex]::match((.\AdFind.exe -b 'DC=domain,DC=com' -f 'sAMAccountType=805306368' -c),'\d{5}').value) 2> $null } 17 { ([regex]::match((.\AdFind.exe -b 'DC=domain,DC=com' -sc adobjcnt:user -c),'\d{5}').value) 2> $null } } } # Check for ($i = 1; $i -le 17; $i++) { if ($i -ge 15) { $count = Get-QueryResult -Id $i } else { $count = (Get-QueryResult -Id $i | Measure-Object).Count } [PSCustomObject]@{ Query = $i Count = $count } } # Measure for ($i = 1; $i -le 17; $i++) { New-Variable -Name "query$i" -Value $('{0:N2}' -f (Measure-Command -Expression { Get-QueryResult -ID $i }).TotalSeconds) } [PSObject]@{ 'Get-ADUser -Filter objectClass and objectCategory' = $query1 'Get-ADUser -LDAPFilter objectclass objectcategory' = $query2 'Get-ADObject -Filter objectClass and objectCategory' = $query3 'Get-ADObject -LDAPFilter objectclass objectcategory' = $query4 'Get-ADObject -LDAPFilter sAMAccountType=805306368' = $query5 'Quest' = $query6 '[adsisearcher]' = $query7 'Find-LdapObject objectClass and objectCategory PropertiesToLoad' = $query8 'Find-LdapObject sAMAccountType=805306368 PropertiesToLoad' = $query9 'Find-LdapObject objectClass and objectCategory' = $query10 'Find-LdapObject sAMAccountType=805306368' = $query11 'dsquery user -o samid' = $query12 'dsquery objectClass and objectCategory' = $query13 'dsquery sAMAccountType=805306368' = $query14 'adfind objectClass and objectCategory' = $query15 'adfind sAMAccountType=805306368' = $query16 'adfind -sc adobjcnt:user' = $query17 }.GetEnumerator() | Sort-Object -Property Value | Select-Object -Property @{ Name = 'Query' Expression = {$_.Name} }, @{ Name = 'TotalSeconds' Expression = {[double]$_.Value} } | Sort-Object -Property TotalSeconds | Format-Table -AutoSize
First, I check that all these commands return the same value:
http://bit.ly/2bNwpXl
Result:
http://bit.ly/2bGT9pK
Conclusion : In this scenario, the fastest was :
AdFind.exe -b 'DC=domain,DC=com' -f 'sAMAccountType=805306368' -c
Links :
Download AdFind (adfind.exe)
http://www.joeware.net/freetools/tools/adfind/
Download System.DirectoryServices.Protocols module (S.DS.P.psm1)
https://gallery.technet.microsoft.com/scriptcenter/Using-SystemDirectoryServic-0adf7ef5
Download QAD cmdlets (Get-QADUser)
http://software.dell.com/products/activeroles-server/powershell.aspx
All these tools in one file :
http://bit.ly/2bnCRVk
Note : If you have a faster solution, feel free to comment below so I can update my article.
Real-world example:
Couting the total numbers of users in Active Directory can be useful in some cases.
You could need this information to generate statistics or reports, or maybe you just want to monitor the number of accounts created / removed on regular basis.
Good Series Sir.
Keep them coming.. 🙂
@zerocool18 : Thanks a lot for your feedback. Yes, I will continue the serie here, the next post should come on next month, right now I am pretty busy.
@Jordi Ortiz Domenech : I take in consideration your suggestion, I will update this article in few weeks (including with another suggestion I received).
Never mind, I read your blog. 🙂
http://powershell-guru.com/the-fastest/
Could you please also test with csvde.exe or ldifde.exe? I’m curious 🙂