Retrieve sets of users based on group membership
In this series of columns about Windows Server 2008 R2's Active Directory (AD)-related PowerShell cmdlets, I’ve shown you how to use the get-aduser and search-adaccount PowerShell cmdlets to extract subsets of your AD user accounts based on a range of criteria, but I haven’t yet considered one commonly needed criterion: group membership. This month, I'll use get-adgroupmember and some of its related cmdlets to show you how to retrieve sets of users based on group membership.
Get-adgroupmember's syntax is pretty simple in its basic form:
Thus, to view all the members in a group named folks, you'd type
To unlock the accounts of all members of the folks group, you could feed the output of the get-adgroupmember command to another AD cmdlet, enable-adaccount:
As you've probably guessed, enable-adaccount simply enables disabled accounts. (Who says PowerShell is hard to understand?) Also, I haven’t yet discussed the "|" (or pipeline) character in detail, but in short, its job is to take the output of one command and make it the input of another command. That's pretty neat, because—trust me—doing what that little "one liner" accomplishes using VBScript and the Active Directory Scripting Interface (ADSI) would translate to about 50-75 lines of code, a lot of testing, and a couple days' work for someone who doesn't do it all the time. In contrast, I created the above PowerShell example in about 3 minutes.
If you'd like to create a few groups to test get-adgroupmember, PowerShell has a few cmdlets to create and populate groups. For example, suppose you have three user accounts named (unimaginatively) user1, user2, and user3. You can quickly generate them with this command:
for /l %i in (1 1 3) do (net user user%i PassW0rd /add)
(By the way, don't type that into the PowerShell command prompt; use an old-style Windows command prompt.) Next, create a pair of nested global groups into which you'll place the users. You’ll create a global group named manyfolks and another called folks, then put the folks group into the manyfolks group. PowerShell's group-creating cmdlet is called new-adgroup, which looks like
new-adgroup name scope-of-group
The group's "scope" is either a numeric or textual value, and the cmdlet accepts 0 or domainlocal for a domain local group, 1 or global for a global group, and 2 or universal for a universal group. (In case you were thinking that you would have called it a group type, new-adgroup also has a group type, but it refers to whether a group is a security or distribution group.) The following two commands will create folks and manyfolks:
Next, you’ll want to nest the folks group in the manyfolks group. You can add either a group or a user to a group with the same command, add-adgroupmember. In its most common usage, it looks like
add-adgroupmember groupname newmember1,newmember2,newmember3…
To put the folks group and the user1 account directly in manyfolks, type
add-adgroupmember manyfolks user1,folks
And in case you can't see that, the list user1,folks contains no spaces. You put user2 and user3 into folks like so:
add-adgroupmember folks user2,user3
With the stage set, you can put get-adgroupmember through its paces. If you type
get-adgroupmember manyfolks | ft samaccountname
you'll see output like
That's technically right, but probably not what you wanted. Typically, you'd like to see the users in a nested group regardless of how deeply nested their group is, and you can do that by adding the -recursive switch (which conveniently shortens to just -r) like so:
get-adgroupmember manyfolks -r | ft samaccountname
You'll then get output like
When instructed to use -recursive, get-adgroupmember examines every nested group, pulling out just the non-container (i.e., user or computer) objects.
Before I go, did you notice something strange about the add-adgroupmember and new-adgroup commands? If not, look at their syntax again. You'll see that they seem to use two non-named parameters each. For example, a more verbose version of the first new-adgroup command would be
new-adgroup -name manyfolks -groupscope global
Why didn't you need to name the -name and -groupscope parameters? Because PowerShell lets its cmdlet authors give us the option to forgo the -whatever parameters, allowing us to just type some set of parameters in the cmdlet invocation in a particular order, making them "positional" rather than "named" parameters. How did I know which parameters could be positional? I read the Help text, which was just a bit cryptic—but I'll decrypt it for you next month.