powershellactive-directorydirectorysearcher

Powershell DirectorySearcher Null Output


I'm writing a powershell script that searches for users inside an Active Directory OU and allows me to reset passwords by choosing matches from a list. I found a Tutorial that uses the System.DirectoryServices.DirectoryEntry and System.DirectoryServices.DirectorySearcher, and modified it like so:

$objDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP:\\[REDACTED]")

##ReadSTDIN
$strSearch = Read-Host -Prompt "Search"
$strCat = "(&(objectCategory=User)(Name=*" + $strSearch + "*))"
## Search Object
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strCat
$objSearcher.SearchScope = "Subtree"
#Load Required Properties into the dynObjLink
$objSearcher.PropertiesToLoad.Add("name")
$objSearcher.PropertiesToLoad.Add("userPrincipalName")
$objSearcher.PropertiesToLoad.Add("SamAccountName")

##Magical Search Function
$colResults = $objSearcher.FindAll() 
$colResults.PropertiesLoaded

#for every returned userID add them to a table
ForEach ($objResult in $colResults)
    {$a++
    $objResult.count
    $objItem = $objResult.Properties
        $objItem.name 
        $objItem.userPrincipalName
    $results.Add($a, $objItem.name + $objItem.userPrincipalName + $objItem.SamAccountName) 
}

#Print Table
$results | Format-Table -AutoSize

This works well enough, but when it prints data I can only get the "first name" value of anything that comes back. Everything else becomes NULL and I can't figure out why.

Name Value                             
---- -----                                                
3    {James3 [REDACTED], $null, $null}      
2    {James2 [REDACTED], $null, $null}      
1    {James1 [REDACTED], $null, $null}         

I've tried different kinds of authentication and manipulating values, but the DirectorySearcher object only seems to collect the "name" value of any record it returns, no matter what I load into it. Help?


Solution

  • Here's a bit shorter (and PowerShell v2-compatible) way of doing this:

    #requires -version 2
    param(
      [Parameter(Mandatory=$true)]
        [String] $SearchPattern
    )
    
    $searcher = [ADSISearcher] "(&(objectClass=user)(name=$SearchPattern))"
    $searcher.PageSize = 1000
    $searcher.PropertiesToLoad.AddRange(@("name","samAccountName","userPrincipalName"))
    $searchResults = $searcher.FindAll()
    if ( $searchResults.Count -gt 0 ) {
      foreach ( $searchResult in $searchResults ) {
        $properties = $searchResult.Properties
        $searchResult | Select-Object `
          @{Name = "name";              Expression = {$properties["name"][0]}},
          @{Name = "sAMAccountName";    Expression = {$properties["samaccountname"][0]}},
          @{Name = "userPrincipalName"; Expression = {$properties["userprincipalname"][0]}}
      }
    }
    $searchResults.Dispose()
    

    Note that there's no need to build a list and output afterwards. Just output each search result. Put this code in a script file and call it:

    PS C:\Scripts> .\Searcher.ps1 "*dyer*"
    

    If you omit the parameter, PowerShell will prompt you for it (because the parameter is marked as mandatory).