Summary: Sorting lists of data in VBScript often involved writing complex code. The Sort cmdlet in Windows PowerShell makes that task easier.

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I need to be able to use Windows PowerShell to list the members of a group in Active Directory Domain Services (AD DS) in alphabetical order. The reason for this is I would like to compare the memberships of a couple of different groups, and if the members are not in alphabetical order, it makes the comparison more difficult.

-- TM

Hey, Scripting Guy! Answer

Hello TM,

Microsoft Scripting Guy Ed Wilson here. Today is a road trip day. My significant other and I woke before dawn and began our preparations for departure. It seems, at times, that NASA space missions are more impromptu than our road trips. We packed my laptop, power adapter, camera, a feedbag, and three Zunes (his, hers, and ours). We headed for open spaces.

It seems that at times the Windows PowerShell team deliberately made Windows PowerShell easy to use. This does not mean that Windows PowerShell is simple. It can get quite complex, but when you learn the basic concepts, you can do some really powerful things quite easily. Sorting is one of those really simple types of things.

The How Can I List the Members of a Group in Alphabetical Order Hey, Scripting Guy! Blog post from November 2004 illustrates one of the more common approaches to sorting data in VBScript—a bubble sort. (The other common technique was to use a recordset and is illustrated in this script from the Scripting Guys Script Repository.)The VBScript from that article is shown here.

SortGroupMembersAlphabetically.vbs

Dim arrNames()
intSize = 0
Set objGroup = GetObject("LDAP://cn=hsgTestGroup,ou=HSG_TestOU,dc=nwtraders,dc=com")
For Each strUser in objGroup.Member
Set objUser = GetObject("LDAP://" & strUser)
ReDim Preserve arrNames(intSize)
arrNames(intSize) = objUser.CN
intSize = intSize + 1
Next
For i = (UBound(arrNames) - 1) to 0 Step -1
For j= 0 to i
If UCase(arrNames(j)) > UCase(arrNames(j+1)) Then
strHolder = arrNames(j+1)
arrNames(j+1) = arrNames(j)
arrNames(j) = strHolder
End If
Next
Next 
For Each strName in arrNames
Wscript.Echo strName
Next

The hsgTestGroup, viewed in the Active Directory Users and Computers administration tool, is shown in the following image.

Image of hsgTestGroup

When the SortGroupMembersAlphabetically.vbs script runs, the output appears that is shown in the following image. I know the picture says Windows PowerShell—this is actually one of my favorite tricks. I run VBScript inside Windows PowerShell. Because of the way the script is written, it would produce several popup dialog boxes, each of which would have to be individually closed. To avoid that, VBScript scripts that use wscript.echo to produce output are commonly run using Cscript. To do this, you normally open a command prompt, type cscript, and provide the path to the script. You can do the same thing using Windows PowerShell: Type cscript and provide the path to the script. I use the Windows PowerShell console for all my command-line needs, and I have not opened a command prompt for more than a year. If it is nothing else, Windows PowerShell is a better command prompt.

Image of output of SortGroupMembersAlphabetically.vbs script

Using the ADSI type accelerator, it requires two lines of code to retrieve the group membership and sort the list. The script first makes a connection to the group in Active Directory Domain Services (AD DS), and retrieves the member property. The members are piped to the Foreach-Object cmdlet where a connection is made to each of the groups. The result is piped to the Sort-Object cmdlet (alias is sort) and then the name is selected by the Select-Object cmdlet (alias is select). The Get-SortedGroupMembership.ps1 script is shown here.

Get-SortedGroupMembership.ps1

([adsi]"LDAP://cn=hsgTestGroup,ou=HSG_TestOU,dc=nwtraders,dc=com").member |

ForEach-Object {[adsi]"LDAP://$_"} | sort name | select name

When the Get-SortedGroupMembership.ps1 script runs inside the Windows PowerShell ISE, the result appears that is shown in the following image.

Image of result of running Get-SortedGroupMembership.ps1 script in Windows PowerShell ISE

One reason for using the ADSI type accelerator would be if you do not have access to a domain that contains a domain controller that is running Windows Server 2008 R2.

For more information about the different approaches to working with AD DS, refer to Monday’s Hey Scripting Guy! Blog post.

If you do have access to a Windows Server 2008 R2, you have access to the Active Directory Windows PowerShell module. After that module is loaded, you can use the Get-ADGroupMember cmdlet to retrieve the group. The good thing about using the Get-ADGroupMember cmdlet is you do not have to type the entire distinguished name of the group as was done in the two previous scripts. After you have the group membership, you can sort by using the Sort-Object cmdlet, and even create a nice table with the name, sid, and objectclass of the object. The Windows PowerShell command is shown here:

Get-ADGroupMember hsgtestgroup -Recursive | sort name | ft name, sid, objectClass -a

When the command runs, the output appears that is shown in the following image.

Image of output when command is run

TM, that is all there is to using Windows PowerShell to sort the members of a group found in AD DS. User Management Week will continue tomorrow when we will talk about adding a domain user to the local administrators group.

We invite you follow us on Twitter and Facebook. If you have any questions, send email to us at scripter@microsoft.com, or post them on the Official Scripting Guys Forum.. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys