Searching through AD OU Units

I am having an issue searching for users with specific criteria and not producing duplicate results.

Our company has an AD structure where we have ‘HostedClient’ OU’s defined within parent ‘Hosted_OU’. Also for a large handful of ‘HostedClientX’ OU’s we may have other Sub_Ou’s defined within them with even more users. User accounts are only defined at the HostedClientX_OU or within the sub OU ‘HostedClientXSub_OU’.


	- Hosted_OU
		- HostedClient1_OU
 		- HostedClient2_OU
		- HostedClient3_OU
		- HostedClient50_OU
			- HostedClient50Sub_OU
		- HostedClient51_OU
			- HostedClient51Sub_OU
		-Hosted Client52_OU
		- HostedClient140_OU

My objective is to produce a list of users from all Company OU’s with certain criteria. In this example, I am producing a list of the Client (aka the Company they belong to), their name, their home directory that points to w2k3 server, and their last login time.

$TPHosted = Get-ADOrganizationalUnit -searchBase "OU=Hosted_OU, DC=HostingCompany,DC=local" -Filter *
foreach ($TPclient in $TPHosted)
  $CompanyOU = [string]$TPclient.Name    
  $OUPath = [string]$TPClient.DistinguishedName 
  #Get-ADUser -SearchBase $OUPath -filter {homedirectory -like '\\w2k3*'} -Properties * | Select-Object Name, HomeDirectory,@{N='LastLogon'; E={[DateTime]::FromFileTime($_.LastLogon)}}  
  Get-ADUser -SearchBase $OUPath -filter {homedirectory -like '\\w2k3*'} -Properties * |  
         $properties = @{
         Client = $CompanyOU;
         Name = [string]$_.Name;
         HDrive =  [string] $_.homedirectory;
         LastLogonTime = [DateTime]::FromFileTime($_.LastLogon)
         Mail = $_.mail
                  $object = New-Object -TypeName PSObject -Property $properties
         $objectCollection = $objectCollection + $object
    }#End of Middle ForEach-Object
}#End of Main ForEach-Object
$objectCollection | ft Client, Name, HDrive, LastLogonTime, Mail

Problem here is that I am getting duplicate results. There will be users listed with company name ‘Hosted_OU’ AND the same user at the OU under that ‘HostedClient1_OU’ (NO USERS ARE DEFINED IN THE ‘HOSTED_OU’ LEVEL…ONLY SUB OU’S)


Client  	   Name	         Hdrive	           LastLogin
Hosted_OU	   John Smith	\\w2k3-Server1     2/21/2017
HostedClient53_OU  John Smith	\\w2k3-Server1      2/21/2017

I started looking at the get-adorganizationalUnit parameters and started working wit ‘searchscope’ parameters.

Get-ADOrganizationalUnit -searchscope subtree -searchBase “OU=Hosted_OU, DC=HostingCompany,DC=local” -Filter *
This seems to produce the same results as above where I see users within the ‘Hosted’ OU where I shouldn’t.

Get-ADOrganizationalUnit -searchscope onelevel -searchBase “OU=Hosted_OU, DC=HostingCompany,DC=local” -Filter *
This seems to eliminate the duplicate entry at the ‘Hosted_OU’ level, however I loose the results of the users who are at the sub ou level ‘HostedClientXXSub_OU’

My stab at getting this to work is to stay with my one level subtree searchscop parameter and then test to see if there are sub ou’s within the current OU that I am searching. If not, move on to the next OU. If so, then do another search for users at the second level.

Was wondering if there is an easier method to this since I don’t feel that this AD structure is unique.

Example PseudoCode that I think ‘might’ work.:

Get-ADOrganizationalUnit -searchscope onelevel -searchBase "OU=Hosted_OU, DC=HostingCompany,DC=local" -Filter *
               if (OU contains sub_OU's){
                 $subOUs = Create Array Sub_OU's 

                 foreach ($ou in $subOUs){
                  Get-aduser of $OU with predefined criteria
                 }#End For Each
                }#end if

         }#End ForEach-Object

Your original code should work if you add the -SearchScope to the Get-ADOrganizationalUnit command.

$TPHosted = Get-ADOrganizationalUnit -searchBase "OU=Hosted_OU, DC=HostingCompany,DC=local" -Filter * -SearchScope OneLevel

The problem is that without the -SearchScope set, the Get-ADOrganizationalUnit command returns the OU at the -searchBase as well as all of the child OUs since “SubTree” is the default value. As a result when your code looped through the returned OUs, it scanned and returned all accounts under the Base OU (including subOUs of the baseOU), then looped through each childOU, creating the duplicates. “Base” returns just the OU defined in the -searchBase, and -OneLevel returns just the immediate children of the -searchBase OU, but not the baseOU itself.

Since your code is expecting to loop through the children of the baseOU in order to do the Get-ADUser for that structure, adding -SearchScope OneLevel should resolve your issue since this eliminates the baseOU from the list results.