PowerShell's Active Directory (AD)-related search commands (get-aduser, get-adgroupmember, search-adaccount, and so on) are some of the things that attracted me most to the new Windows Server 2008 R2 cmdlets, and that’s why I've been focusing on them for the past few months. I think it’s pretty neat to be able to run a query such as

get-aduser -f {title -eq "claims adjuster" -and manager -eq "cn=JFarkus,cn=users,dc=bigfirm,dc=com"} -searchbase "ou=Montana,dc=bigfirm,dc=com"
to retrieve all the claims adjusters at Bigfirm.com who are from the Montana OU and who have a manager with the username JFarkus. And that example took me only about 30 seconds to formulate! The hardest part was remembering that I had to use a distinguished name (DN) for a manager—and when I remember how long it took me to do something like that in VBScript, I, get a little dizzy.

I'm grateful for the power of the PowerShell cmdlets, but they can be frustrating because, really, they're nothing more than a prettier front end on LDAP queries, and so things that your intuition tells you should work—don’t (for example, searching to find the people whose managers' names begin with S.) But when you're using the get-whatever AD commands and find yourself in a corner, don't give up: Rather, just try to attack it from a different angle.

And that brings me to last's month's puzzle. How do you query AD for a group's members, but to return only the group members who also live in a particular OU? How do you find all the members of the group folks who live in the Sales OU?

Hmmm … maybe you could retrieve a group's membership with get-aduser rather than get-adgroupmember. You could slap a -searchbase parameter on the end, and you’d be in good shape. Whenever I'm up against something like this in PowerShell (“Can get-something get a property that will solve the problem?"), I go look at the attributes of the object in question. As you’ve seen before, you can get an extensive list of the attributes that user objects in PowerShell contain by typing

get-aduser -f * | gm
By doing that, I see it: MemberOf. Time to take a look at what a typical MemberOf looks like with this command:

get-aduser -f {samaccountname -eq "mark"} -pr MemberOf | ft name,memberof -auto
Recall that ft is format-table and that if you don't include -pr MemberOf in get-aduser, you won't get that attribute delivered down the pipeline. MemberOf ends up looking like {CN=Enterprise Admins,CN=Users,DC=Bigfirm,DC=com,CN=Schema Admins,CN=Users,DC=Bigfirm,DC=com… and so on, so essentially MemberOf is a comma-delimited list of the DNs of the various groups that the user named mark is a member of. (And if format-table's output is a bit too 1980s teletype for you, remember that if you have the PowerShell ISE feature installed, you can use the grid view, as in

get-aduser -f {samaccountname -eq "mark"} -pr MemberOf | ogv
and you can install the PowerShell ISE from PowerShell itself by typing ipmo servermanager and then add-windowsfeature powershell-ise, but unfortunately you'll have to close your PowerShell window and open a new one to get GridView working.)

Next, you'd try using MemberOf in a get-aduser filter. Maybe this will show us all the people in the Enterprise Admins group?

get-aduser -f {MemberOf -like "*Enterprise Admins*"}
But unfortunately that returns no results because MemberOf seems to want comparisons with exact DNs of groups, and so this returns the members of the Enterprise Admins group:

get-aduser -f {Memberof -eq "CN=Enterprise Admins,CN=Users,DC=Bigfirm,DC=com"}
Now, that retrieves the members of the Enterprise Admins group, and the only pain that it exacts is that you've got to know the DN of that or any other group. It's simple to get a list of the groups in a domain and their DNs, though:

get-adgroup -f *|ft name,distinguishedname -auto
And from there it's all cut and paste. To return to the original question—“What members of the group folks are in the Sales OU?"—you could formulate it like this:

get-aduser -f {memberof -eq "CN=Folks,CN=Users,DC=Bigfirm,DC=com"} -searchbase "ou=sales,dc=bigfirm,dc=com"
Oh, and while we're at it, you could even make that query against a Global Catalog (GC) by adding - servername:port, as a member of the AD PowerShell team pointed out to me recently. (Thanks, Saket!). Assuming you want to run the query against a DC named DC4 that was also a GC server, I could run this query:

get-aduser -f {memberof -eq "CN=Folks,CN=Users,DC=Bigfirm,DC=com"} -searchbase "ou=sales,dc=bigfirm,dc=com" -server dc4:3268
The morals of this month's story, then, are as follows: It never hurts to give an object's list of attributes another look, and never assume that you should be able to use wildcards against DNs. See you next month!