When working in an unfamiliar Active Directory environment with little or no documentation, knowing where things are (or where they are more likely to be) can help you get started a lot more quickly. And one question I always have is “where do you store your server objects in AD?”
When approaching this problem, I came up with Test 1 (below) as my initial solution – querying for all servers, and then grouping by OU.
Dr Google seems to suggest that the rest of the Internet prefers the approach in Test 2; where you find all OUs, then interrogate each OU for any servers.
So, here are both versions. I added the capturing of timestamps to calculate which one ran faster. So if you use either of the below scripts, you can strip out the time-related bits.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#---------- Test 1 ----------# # Record start of test 1 $starttime = get-date; # Get all servers from AD $servers = get-adcomputer -filter {operatingsystem -like "*server*"}; # Loop through each server found foreach ($server in $servers) { # Strip out OU from DN $dnsplit = $server.distinguishedname -split ","; $server.ou = $dnsplit[1..$dnsplit.count] -join ","; } # Save results into a table and sort from highest to lowest $resulttable1 = $servers | group-object -noelement -property ou | sort count -desc; # Record end of test 1 $endtime = get-date # Calculate total test time $test1time = new-timespan -start $starttime -end $endtime; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#---------- Test 2 ----------# # Record start of test 2 $starttime = get-date; # Define array of strings to store results $resulttable2 = @(); # Get all OUs from AD $ous = get-adorganizationalunit -filter *; # Loop through each OU found foreach ($ou in $ous) { # Define output structure $resultline = "" | select count, ou; # Get amount of servers in this OU $resultline.count = (get-adcomputer -filter {operatingsystem -like "*server*"} -searchbase $ou.distinguishedname -searchscope 1| measure-object).count; $resultline.ou = $ou; # Add to the resutls table only if servers are found if ($resultline.count -gt 0) { $resulttable2 = $resulttable2 + $resultline; } } # Sort from highest to lowest $resulttable2 = $resulttable2 | sort count -desc; # Record end of test 2 $endtime = get-date; # Calculate total test time $test2time = new-timespan -start $starttime -end $endtime |
1 2 3 4 5 6 |
#---------- Output ----------# # Show results of times taken to perform each test write-host -foregroundcolor "red" "Test 1:" $test1time.totalseconds "seconds`nTest 2:" $test2time.totalseconds "seconds"; |
In my case, Test 1 proved to be the faster solution to execute:
And don’t forget that the actual results you are going to use are stored in the $resulttable1/$resulttable2 variables.
get-adcomputer : The term ‘get-adcomputer’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, v
erify that the path is correct and try again.
How to recognize the command?
Thanks
You need to use this, first:
import-module activedirectory
That assumes you’re on a Domain Controller, or have the AD Powershell cmdlets installed where you’re running the script from.