Hey, Scripting Guy! Question

Hey, Scripting Guy! I’m looking for a script that can get the memberships of two different groups, compare them, and then write out the differences. Can you help?

-- LS

SpacerHey, Scripting Guy! AnswerScript Center

Hey, LS. When we received your question a week or so ago we thought, “That’s a good question. Let’s put it on the list and answer it sometime.” Since then we’ve had 3 or 4 more people ask the same question. Well, there’s one thing about us Microsoft Scripting Guys: you might have to ask us 5 or 6 times, but by the 7th time we finally get the hint. Here’s how you can do this.

Because a couple of people specifically mentioned being able to compare the local Administrators group on two different computers that’s the example we’re going to use. But, needless to say, you can compare any two groups using this same technique. Want to compare two groups on the same computer? No problem. Want to compare two Active Directory groups? No problem. How about a local group and an Active Directory group? That’s right: no problem.

To begin with, we need some code that can grab the list of members of our two local groups and then stash that information somewhere so that we can then compare the two lists. Getting the membership is easy; here’s a script that retrieves the members of the Administrators group on the computer atl-ws-01:

strComputer = "atl-ws-01"
Set objGroup = GetObject("WinNT://" & strComputer & "/Administrators")
For Each objUser in objGroup.Members
     Wscript.Echo objUser.Name   
Next

Of course, the preceding script echoes the user names to the screen. We don’t really want to that; instead, we want to hang on to those user names so that we can then compare them with the names we get from the second computer. Fortunately, there’s an easy way to do this: we just stuff the names into a Dictionary object:

Set objGroup1 = CreateObject("Scripting.Dictionary")

strComputer = "atl-ws-01"
Set objGroup = GetObject("WinNT://" & strComputer & "/Administrators")
For Each objUser in objGroup.Members
    objGroup1.Add objUser.Name, objUser.Name   
Next

If you aren’t familiar with the Dictionary object, you might want to check out this section of the Microsoft Windows 2000 Scripting Guide. For now, consider the Dictionary object a collection of key/value pairs; typically you store things like states and their state capitals in a Dictionary object:

Washingon/Olympia
Oregon/Salem
Idaho/Boise

In this example, Idaho is a key and Boise is its corresponding value. Oregon is a key, and Salem is its corresponding value.

The whole idea here is that you can ask a question like, “What is the capital of Washington?” and the script can check the key/value pair and respond, “Olympia.” It does this by searching for the key - Washington - and then reporting back the value: Olympia. Of course, in our case, we’re really only interested in the keys; we want to be able to ask a question like, “Is Bob a member of Group 1?” However, since the Dictionary object requires both a key and a value, we end up putting the same information (the user name) in each. Thus we end up with a list like this:

Bob/Bob
Jill/Jill
Joe/Joe
Susan/Susan

But don’t worry about the values. The important thing is that the collection of keys looks like this:

Bob
Jill
Joe
Susan

If we repeat this process for Computer 2 (using a second Dictionary object to hold the membership of that group), we’ll have a script that looks similar to this:

Set objGroup1 = CreateObject("Scripting.Dictionary")
Set objGroup2 = CreateObject("Scripting.Dictionary")

strComputer = "atl-ws-01"
Set objGroup = GetObject("WinNT://" & strComputer & "/Administrators")
For Each objUser in objGroup.Members
    objGroup1.Add objUser.Name,objUser.Name   
Next

strComputer = "atl-ws-02"
Set objGroup = GetObject("WinNT://" & strComputer & "/Administrators")
For Each objUser in objGroup.Members
    objGroup2.Add objUser.Name,objUser.Name   
Next

No, sorry, we aren’t done yet. But we’re getting close. We now have the two membership lists, and all we have to do is compare them and write out any differences. How do we do that? As it turns out, you can use a For Each loop to cycle through all the keys in a Dictionary object. For example, if you want to echo all the key names you can use code like this:

colKeys = objGroup1.Keys
For Each strUser in colKeys
    Wscript.Echo strUser
Next

Of course, we don’t want to echo the membership list, we want to find out who is in Group 1 and then check to see if they are also in Group 2. To do that, we use the For Each loop to get the first user in Group 1 - Bob - and we then use the Dictionary object’s Exists method to see if Bob is also in Group 2. If he is, that’s fine; if he’s not, we then echo a message that says “Bob is not in Group 2.” We know, that sounds complicated, but it only takes a few lines of code:

colKeys = objGroup1.Keys
For Each strUser in colKeys
    If Not objGroup2.Exists(strUser) Then
        Wscript.Echo strUser & " is not in Group 2."
    End If
Next

We then repeat the process with Group 2, checking to see if all the users in that group are members of Group 1. When that part of the script ends, we’ll have a list of the differences between the two groups.

Here’s the completed script. Again, it might look a little weird, but that’s simply because people don’t use the Dictionary object very often. It’s actually very simple, though, and even - heaven forbid! - has some logic to it:

Set objGroup1 = CreateObject("Scripting.Dictionary")
Set objGroup2 = CreateObject("Scripting.Dictionary")

strComputer = "atl-ws-01"
Set objGroup = GetObject("WinNT://" & strComputer & "/Administrators")
For Each objUser in objGroup.Members
    objGroup1.Add objUser.Name,objUser.Name   
Next

strComputer = "atl-ws-02"
Set objGroup = GetObject("WinNT://" & strComputer & "/Administrators")
For Each objUser in objGroup.Members
    objGroup2.Add objUser.Name,objUser.Name   
Next

colKeys = objGroup1.Keys
For Each strUser in colKeys
    If Not objGroup2.Exists(strUser) Then
        Wscript.Echo strUser & " is not in Group 2."
    End If
Next

colKeys = objGroup2.Keys
For Each strUser in colKeys
    If Not objGroup1.Exists(strUser) Then
        Wscript.Echo strUser & " is not in Group 1."
    End If
Next