Search AD 2003 Forest With Powershell
I am trying to write a script to populate a number of DGs. First it needs to search a 2003 forest for user objects by the employeeID attribute, then perform a get-recipient to resolve the user or contact, then populate the DG. First, I wrote a function to
search each AD domain by employeeID attribute and this is where I am having the first issue. When it searches the domain that actually contains the object, the result is OK. However, when it searches the domain that does not contain the object, instead of
returning a null result, it returns "0". I can use an if statement to only act on the result that is not a "0", but to me this seems like a kludge and is not very elegant. Here is the function:
Function SearchAD ($LDAPFilter)
{
$objForest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$DomainList = @($objForest.Domains | Select-Object Name)
$Domains = $DomainList | foreach { $_.Name }
foreach ($Domain in $Domains)
{
$ADsPath = [ADSI]"LDAP://$Domain"
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher($ADsPath)
$objSearcher.Filter = $LDAPFilter
$objSearcher.PageSize = 1000
$objSearcher.SearchScope = "Subtree"
$PropList = "mail"
foreach ($Property in $PropList){$objSearcher.PropertiesToLoad.Add($Property)}
$Results = $objSearcher.FindAll()
}
}
The next issue occurs in the scipt from which I am calling the function. I am attempting to feed the results of the AD search into a get-recipient cmdlet so that I can then use it to add to the DG. However, when running the cmdlet, I receive the error
"Get-Recipient : Cannot bind parameter 'Identity'. Cannot convert the "System.DirectoryServices.ResultPropertyValueCollection" value of type "System.DirectoryServices.ResultPropertyValueCollection" to type "Microsoft.Exchange.Configuration.Tasks.RecipientIdParameter"."
So, to try and fix this, I attempted to call the "ToString()" method to convert the value. However, the value to which it is converted is "System.DirectoryServices.SearchResult" and not the actual value of the result, which is supposed to be the "mail" attribute.
Here is the script:
Param($InputFile = $(Read-Host -Prompt 'Provide path and file name for list of Employee IDs'))
$EmplIDList = Get-Content $InputFile
Write-Host $EmplIDList
foreach ($EmplID in $EmplIDList)
{
$Results = SearchAD -LDAPFilter "(&(objectCategory=Person)(|(objectClass=User)(objectClass=Contact))(employeeID=$emplID))"
Write-Host $Results
foreach ($Result in $Results)
{
if ($Result -ne 0)
{
$Item = $Result.Properties
$Mail = $Item.mail
}
}
$RecipientObj = Get-Recipient -Identity $Mail
Write-Host $RecipientObj
}
May 3rd, 2010 5:37pm
Param($InputFile = $(Read-Host -Prompt 'Provide path and file name for list of Employee IDs'))
$EmplIDList = Get-Content $InputFile
Write-Host $EmplIDList
foreach ($EmplID in $EmplIDList)
{
$Results = SearchAD -LDAPFilter "(&(objectCategory=Person)(|(objectClass=User)(objectClass=Contact))(employeeID=$emplID))"
Write-Host $Results
foreach ($Result in $Results)
{
if ($Result -ne 0)
{
$Item = $Result.Properties
$Mail = $Item.mail
}
}
$RecipientObj = Get-Recipient -Identity $Mail
Write-Host $RecipientObj
}
Try to change this
foreach ($Result in $Results)
{
if ($Result -ne 0)
{
$Item = $Result.Properties
$Mail = $Item.mail
}
}
to this
foreach ($Result in $Results)
{
$de = $Result.GetDirectoryEntry()
if ($de -ne $null)
{
#$Item = $Result.Properties
$Mail = $de.mail
}
$de.Close()
$de.Dispose()
}
Regards,Laeeq Qazi|Team Lead(Exchange + Sharepoint + BES + DynamicsCRM)
www.HostingController.com
Free Windows Admin Tool Kit Click here and download it now
May 3rd, 2010 5:54pm
Hi,
Also you will have to put
$RecipientObj = Get-Recipient -Identity $Mail.Value
instead of
$RecipientObj = Get-Recipient -Identity $Mail
I have successully tested.Laeeq Qazi|Team Lead(Exchange + Sharepoint + BES + DynamicsCRM)
www.HostingController.com
May 3rd, 2010 6:52pm
I was thinking that with the recipient object. What about getting the search not to return zeros at all? Is that just the way the search works?
Free Windows Admin Tool Kit Click here and download it now
May 3rd, 2010 8:13pm
I was thinking that with the recipient object. What about getting the search not to return zeros at all? Is that just the way the search works?
If there will not be matching result then search will always be returning 0 items which u can check by putting an if
if( $Results.Count > 0)
you put Write-host "Got: $($Results.Count)" to print the search result count.
also if result is 0 then this loop
foreach ($Result in $Results)
{
}
wont be entered at all.
Hope this help u. Feel free to post anything which confuses you. I have checked your script without dividing it into method and it runs fine for me but for some other filter offcourse.
Regards,
Laeeq Qazi|Team Lead(Exchange + Sharepoint + BES + DynamicsCRM)
www.HostingController.com
May 3rd, 2010 10:20pm
Are you saying to put that in the function or in the script? I tried it in the function and it works if I just run the statements themselves. However, if I place your recommended changes in the script after the function runs, it does not work, saing that
basically the object type doesn't have the GetDirectoryEntry() method. But, if I put that loop in the function, it returns 2 zeros and not the directory object that corresponds to the employeeID attribute.
Free Windows Admin Tool Kit Click here and download it now
May 3rd, 2010 10:44pm
Are you saying to put that in the function or in the script? I tried it in the function and it works if I just run the statements themselves. However, if I place your recommended changes in the script after the function runs, it does not work, saing that
basically the object type doesn't have the GetDirectoryEntry() method. But, if I put that loop in the function, it returns 2 zeros and not the directory object that corresponds to the employeeID attribute.
Move your loop into function, and do all your processing within the function.
I modified your script and queried a user on the basis of SamAccountName, and here is my script which I tested.
So firstly you run you script simply like mine for one user, if it succeed then try for all users:
#I have tested this filter
#$LDAPFilter= "(&(objectClass=User)(samAccountName= user1) )"
$emplID= "Put EmployeID here"
$LDAPFilter= "(&(objectCategory=Person)(|(objectClass=User)(objectClass=Contact))(employeeID=$emplID))"
$objForest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$DomainList = @($objForest.Domains | Select-Object Name)
$Domains = $DomainList | foreach { $_.Name }
foreach ($Domain in $Domains)
{
Write-host $Domain
$ADsPath = [ADSI]"LDAP://$Domain"
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher($ADsPath)
$objSearcher.Filter = $LDAPFilter
$objSearcher.PageSize = 1000
$objSearcher.SearchScope = "Subtree"
$PropList = "mail"
foreach ($Property in $PropList){$objSearcher.PropertiesToLoad.Add($Property)}
$Results = $objSearcher.FindAll()
Write-host "Got: $($Results.Count)"
foreach ($Result in $Results)
{
$de = $Result.GetDirectoryEntry()
if ($de -ne $null)
{
$Mail = $de.mail
Write-host "Mail: $($Mail)"
}
$de.Close()
$de.Dispose()
$RecipientObj = Get-Recipient -Identity $Mail.Value
Write-Host $RecipientObj
}
}
If it works for one user then integrate this code with other part of your script.
Regards,
Laeeq Qazi|Team Lead(Exchange + Sharepoint + BES + DynamicsCRM)
www.HostingController.com
May 3rd, 2010 11:48pm
Also
Change this script block
foreach ($Result in $Results)
{
$de = $Result.GetDirectoryEntry()
if ($de -ne $null)
{
$Mail = $de.mail
Write-host "Mail: $($Mail)"
}
$de.Close()
$de.Dispose()
$RecipientObj = Get-Recipient -Identity $Mail.Value
Write-Host $RecipientObj
}
to
foreach ($Result in $Results)
{
$de = $Result.GetDirectoryEntry()
if ($de -ne $null)
{
$Mail = $de.mail
Write-host "Mail: $($Mail)"
$de.Close()
$de.Dispose()
$RecipientObj = Get-Recipient -Identity $Mail.Value
Write-Host $RecipientObj
} }
Laeeq Qazi|Team Lead(Exchange + Sharepoint + BES + DynamicsCRM)
www.HostingController.com
Free Windows Admin Tool Kit Click here and download it now
May 3rd, 2010 11:53pm
Thanks for all the help, Laeeq. I got it working, then we realized that not all the user accounts had Employee ID populated. So, we need to have this resolved first. But this is great for future reference.
May 4th, 2010 6:07pm
Thanks for all the help, Laeeq. I got it working, then we realized that not all the user accounts had Employee ID populated. So, we need to have this resolved first. But this is great for future reference.
You are welcome, glad to know that it somehow worked for you. It is always good practice to start from one user and testing one part of the script at a time.
CheersLaeeq Qazi|Team Lead(Exchange + Sharepoint + BES + DynamicsCRM)
www.HostingController.com
Free Windows Admin Tool Kit Click here and download it now
May 4th, 2010 6:12pm