I'm trying to grab out some information from Active Directory using Powershell, but I get some strange behavior. Here's my script:
$toFind = ( 'bobjones', 'samsmith' )
filter Get-AdUser {
$strFilter = "(&(objectCategory=User)(sAMAccountName=$_))"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$colProplist = ("name", "department")
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
($objSearcher.FindAll() | %{$_.Properties})
}
"paul" | get-aduser # Works
$toFind | get-aduser # Doesn't work?!
The former prints out what I expect, a table of properties; the latter ends up just printing "0 1" repeatedly though I'm not sure why. Why would the single case work but not the array?
You may have to specify a foreach loop like foreach ($user in $toFind) { get-aduser $user }
What happens if you simply type $toFind at the prompt? I'm assuming it would list both names, one per line, like it should.
I tried running this same code against my AD and got the following results: 0 1
Name Value ---- ----- name {Sahnti L. Aphil} adspath {LDAP://CN=Sahnti L. Aphil,OU=Users,OU=Jackson,DC=company,DC=local} 0 1 name {Hamong Justice} adspath {LDAP://CN=Hamong Justice,OU=Users,OU=Jackson,DC=company,DC=local}
Just a sidenote: I would heavily recommend looking into the Quest AD cmdlets package (http://www.quest.com/powershell/activeroles-server.aspx) for all AD-related powershell things. It fills a hole as the builtin AD Support in powershell is pretty crappy. It will save you lots of development time.
Figured it out, it has nothing to do with PowerShell. When you create the DirectoryEntry:
It will return results for your domain only (i.e. if you have an AD forest like "NorthAmerica" and "Europe", it'll only query the one you're in). It just happened that all of the names I was searching for were in another domain.
If you use the constructor to manually specify the Domain, it works pretty well (still haven't figured out how to query all domains yet though...)
What you want to do is query the Global Catalog since you want to search across the entire forest. There are a couple of approaches but the simplest is to change your search root to the GC. e.g.
Alternatively you can query the forest and then ask it for a list of Global Catalogs and use one of those as the initial Directory Entry but this is a simple enough change that will do what you want provided the fields you are searching are in the GC. The search part shouldn't be a problem in your case as you are searching by Username which is global by default but you wont get the Department field back from the search result result because Department is not global by default. To get it you will need to use the Distinguished Name from the search result to do a subsequent AD lookup against the users domain for the full AD user object and then pull the Department out of that. You could change your schema so that Department is global but that would be a bit radical IMO.
You can find the comprehensive list of the default global attributes here.
FYI, the reason you get the output of 0 and 1 is because the call to $objSearcher.PropertiesToLoad.Add() returns the index of the property that was added (0 for the first property, 1 for the second). This will happen once for each user in your script. You can suppress the return value by piping it to Out-Null.