Wonder if someone could point out where I’m going wrong with this one - I’m sure this should be much simpler than I’m making it! I’ve got a list of people’s names (which should match the DisplayName field in Active Directory), for whom I want to the ADUsers (ultimately, I’d look to grab the SAMAccountNames and export them out to another csv).
So, I put the list of names into a csv and tried this:
…where personname is the column header in the csv file.
When I run this I get an error
Get-ADUser : Property: 'PersonName' not found in object of type 'System.Management.Automation.PSCustomObject'
When I do a Get-Member on the imported CSV, I see PersonName listed, but it is a NoteProperty, rather than a property as you’d normally see it. Not sure if that’s significant? Having said that, referencing the property works just fine when I so something slightly simpler like:
We can see this by calling the Get-ADUser cmdlet without the pipeline for the file with Get-Member.
Get-ADUser -Filter * | Select -First 1 | Get-Member -MemberType Properties | Select Name
Name
----
DistinguishedName
Enabled
GivenName
Name
ObjectClass
ObjectGUID
SamAccountName
SID
Surname
UserPrincipalName
It’s still odd that it is not matching by value though, which is odd.
Yet, what appears to be happening, is that header name - PersonName, for whatever reason is getting read in and Get-ADUser is barfing on it.
So, like your example, the following work as well.
The Filter parameter on Get-ADUser does not work directly, it converts it to an ldapFilter behind the scenes. As such, I’m never sure if it’s going to do it correctly, so I avoid it for all but the simplest of searches. Try this:
The alternative, which would work pretty well with OP’s original attempt albeit with some extra $( ) around his variable property accessor, is to use double quotes for the filter.
Yes, all the documentation on -Filter tells you to use braces. Just… don’t. It is a [string] parameter in the documentation (and implementation), so what can often happen is that PS converts the contents of what is actually a [scriptblock] to [string] directly. When this is done, it can completely skip the part where PS usually expands variables in strings.
Thank you all for your help and advice! Those all worked for me!
See, I’d wondered if it didn’t want to play nicely with my pair of braces on the filter argument - I think I tried with quotes, but I think I was missing the second $()! One small change I needed to make to Joel’s solution was to put the comparison part in single quotes to give:
I’m also going to spend a bit more time playing with the -ldapFilter parameter; that looks like it will come in handy.
One more quick follow-up question on this - re the use of -filter *
My assumption was/is that I should probably avoid using this where possible to prevent unnecessary load on the domain controller. Is that right? Not sure exactly how many active users are in my AD, but rough guess is it’s in the region of 5,000.
Oop, nice catch! I tend to forget that you still have to quote the second part because… AD cmdlets are silly, really there’s no explanation for requiring such odd behaviour!
And yes, where possible have some limiting aspect of your user search. If you try to get all users in the domain it’ll cause a good bit of time lag, and probably bog down the network a little bit.
So, either use a filter, or search only in a single OU, or something of that sort to limit the amount of objects the command will return from the DC.
In general, with PS (and I guess with most programming languages!), you should attempt to adhere to the maxim: Filter left, format right.
Basically, that means do all filtering as early as possible to limit the amount of unnecessary memory usage and objects being passed around. Then, do any formatting absolutely last so you retain data in its most useful form as much as possible and save you lots of trouble.