• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 798
  • Last Modified:

VBScript to list number of member in Active Directory

We have about 200 groups in our Active Directory that we want to start doing some cleanup on.  First we just want to find any groups with just 2 or less members.  So far I have this script that will list the members of a group:

On Error Resume Next
 
Set objGroup = GetObject ("LDAP://cn=Accounting,ou=Groups,ou=Exchange Users,dc=OurDomain,dc=com")
objGroup.GetInfo

arrMemberOf = objGroup.GetEx("member")

WScript.Echo "Members:"
For Each strMember in arrMemberOf
  WScript.echo strMember
Next

Open in new window


But note that I had to specify the CN ("Accounting").  Lacking VBScript skill, is there an easy way to cycle through all groups under the "Groups" OU and spit out the list of members if that list is 2 or less members?
0
netjon
Asked:
netjon
  • 9
  • 7
1 Solution
 
sirbountyCommented:
Try this: (modify yourDC and yourDomain below)

on error resume next

Const ADS_SCOPE_SUBTREE = 2

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 

objCommand.CommandText = _
    "SELECT ADsPath FROM 'LDAP://dc=YOURDC,dc=YOURDOMAIN,dc=com' WHERE objectCategory='group' "
    
Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    Set objGrp= GetObject(objRecordSet.Fields("ADsPath").Value)

    If objGrp.GroupType < 0 THen 
      objGrp.GetInfo
      arrMembers = objGrp.GetEx("member")

      If uBound(arrMembers) - 1 < 3 Then
        wscript.echo objGrp.CN & " has less than 3 members..."
      end if
    end if
    objRecordSet.MoveNext
Loop

Open in new window

0
 
netjonAuthor Commented:
I had to tweak it a bit, but with your logic processing, it leaves me with an issue at the end when I want to output the number of members in each group.  Here is what your code has evolved into:

on error resume next

Const ADS_SCOPE_SUBTREE = 2

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile("output.txt", True)

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 

objCommand.CommandText = "SELECT ADsPath FROM 'LDAP://ou=groups,ou=Exchange Users,dc=MyDomain,dc=com' WHERE objectCategory='group' "
    
Set objRecordSet = objCommand.Execute

objFile.WriteLine "The following have less than 3 members:"
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    Set objGrp= GetObject(objRecordSet.Fields("ADsPath").Value)

    If objGrp.GroupType < 0 Then 
      objGrp.GetInfo
      arrMembers = objGrp.GetEx("member")

      If uBound(arrMembers) < 2 Then
        objFile.WriteLine objGrp.CN & Space(40-Len(objGrp.CN)) & uBound(arrMembers)+1
      end if
    end if
    objRecordSet.MoveNext
Loop  

Open in new window


The problem is using uBound(arrMembers) . . . If a group has 1 member, then this will be 0.  But if a group has 0 members, it seems to also be 0.  So my final product gives me a list of groups and their members, except that a "1" [uBound(arrMembers)+1] could mean the group has 0 members OR 1 member.  I know there are groups with 0 members, but can't tell that from the output.

Could there be a way to do an If statement like ...

If uBound(arrMembers) = 0 Then
    If arrMembers.ContainsNothing Then objFile.WriteLine "0"
    Else objFile.WriteLine "1"
    End If
End If

Open in new window


That was obviously pseduo-code.  Not sure if it's possible with VBScript.
0
 
sirbountyCommented:
Ok, slightly different scope, but if that's what you want, then this should take care of it for you:

on error resume next

Const ADS_SCOPE_SUBTREE = 2

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile("output.txt", True)

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 

objCommand.CommandText = "SELECT ADsPath FROM 'LDAP://ou=groups,ou=Exchange Users,dc=MyDomain,dc=com' WHERE objectCategory='group' "
    
Set objRecordSet = objCommand.Execute

objFile.WriteLine "The following have less than 3 members:"
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    Set objGrp= GetObject(objRecordSet.Fields("ADsPath").Value)

    If objGrp.GroupType < 0 Then 
      i = 0
     For Each strUser in objGrp.Member
        i = i + 1
      Next
      If i < 3 then objFile.WriteLine objGrp.CN & Space(40-Len(objGrp.CN)) & i
   end if
   objRecordSet.MoveNext
Loop  

Open in new window

0
Protect Your Employees from Wi-Fi Threats

As Wi-Fi growth and popularity continues to climb, not everyone understands the risks that come with connecting to public Wi-Fi or even offering Wi-Fi to employees, visitors and guests. Download the resource kit to make sure your safe wherever business takes you!

 
netjonAuthor Commented:
That still gives me the same number count for each group, meaning all is well except that groups with 0 are showing up as having 1 member.
0
 
netjonAuthor Commented:
You know what the problem could be . . . I added the output of arrMembers in addition to the count, and one group I know has 0 member that shows up having 1 member shows that the member is a user called Jerry.  Coincidentally, the previously listed group only had Jerry in it.  So maybe we should be cleaning out arrMember on each loop iteration?  Looks like on 0 members it gets stuck with previous garbage.
0
 
sirbountyCommented:
The latest code above doesn't use arrMember any longer.  And i gets reset to 0 on each record, so that shouldn't pose a problem...
0
 
netjonAuthor Commented:
Weird.  Well I'm definitely only getting 1's and 2's on my output.  The 2's are correct, but 1's are being listed for groups with 0 members and groups with 1 member.
0
 
netjonAuthor Commented:
What's the best way, given the most recent code revision you've given, to output the names of the members as well as the count?
0
 
netjonAuthor Commented:
What is the purpose of:

If objGrp.GroupType < 0 Then i = 0

Open in new window


Why not just
i = 0

Open in new window

0
 
sirbountyCommented:
You can remove that line - it limits the groups to security groups.
This should display the members.  Let me know how you make out.

on error resume next

Const ADS_SCOPE_SUBTREE = 2

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile("output.txt", True)

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 

objCommand.CommandText = "SELECT ADsPath FROM 'LDAP://ou=groups,ou=Exchange Users,dc=MyDomain,dc=com' WHERE objectCategory='group' "
    
Set objRecordSet = objCommand.Execute

objFile.WriteLine "The following have less than 3 members:"
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    Set objGrp= GetObject(objRecordSet.Fields("ADsPath").Value)

      i = 0
     For Each strUser in objGrp.Member
        i = i + 1
      Next
      If i < 3 then
        For Each strUser in objGrp.Member
          wcsript.echo strUser
        Next
        objFile.WriteLine objGrp.CN & Space(40-Len(objGrp.CN)) & i
    end if
   end if
   objRecordSet.MoveNext
Loop  

Open in new window

0
 
netjonAuthor Commented:
Ok, in doing so my output looks like this:

Group_I_Know_Has_0_Members     -     1 member
        Members:
Group_I_Know_Has_1_Member       -     1 member
        Members:
Group_I_Know_Has_2_Members      -     2 members
        Members: Jerry, John
Group_I_Know_Has_2_Members      -     2 members
        Members: Jerry, Accounting
Group_I_Know_Has_1Member        -      1 member
        Members:
[...]


So groups with 0 and 1 members not only show as having one member in variable "i" but also have no "strUsers" in objGroup.Member.

What do you make of that?  Do you have a domain environment you could test this with?
0
 
sirbountyCommented:
Yeah, testing somewhat here, but haven't really found a similar situation in what I'm scanning.

The issue may be the group class, so give this a shot and let me know what you find....

on error resume next

Const ADS_SCOPE_SUBTREE = 2

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile("output.txt", True)

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 

objCommand.CommandText = "SELECT ADsPath FROM 'LDAP://ou=groups,ou=Exchange Users,dc=MyDomain,dc=com' WHERE objectCategory='group' "
   
Set objRecordSet = objCommand.Execute

objFile.WriteLine "The following have less than 3 members:"

objRecordSet.MoveFirst

Do Until objRecordSet.EOF
  i = 0
  Set objTypes = CreateObject("Scripting.Dictionary")
  Set objUsers = CreateObject("Scripting.Dictionary")

  Set objGrp= GetObject(objRecordSet.Fields("ADsPath").Value)

  For Each strUser in objGrp.Member
    i = i + 1
    Set objMember = GetObject("LDAP://" & strUser)
    strType = objMember.Class

    If Not objTypes.Exists(strType) Then 
      objTypes.Add strType, "1"
    Else
      objTypes.Item(strType) = objTypes.Item(strType) + 1
    End If
    
    objUsers.Add strUser, i
    
  Next
  
  If i < 3 then
    objFile.WriteLine objGrp.CN & " contains: "
    For Each oUser in objUsers
      objFile.WriteLine oUser 
    Next
    For Each oType in objTypes 
      If Trim(oType) <> "" Then objFile.WriteLine vbTab & oType & " count: " & objTypes.Item(oType)
'    objFile.WriteLine objGrp.CN & Space(40-Len(objGrp.CN)) & i
    Next
    objFile.WriteLine
  End If

  objRecordSet.MoveNext
Loop   

objFile.Close

Open in new window

0
 
netjonAuthor Commented:
Eh, I've figured out a workaround that at least works.

I do an If statement to test if ( i = 1 ) and then a nested If statement to test if ( objGrp.Member = "" ) which would signify a 0-member group.  I then adjust the output to just say "0."  Also, to list users for groups of 1-member, I need to output objGrp.Member directly -- Cycling through that array with strUser works with groups of more than one member, but for some reason outputs nothing for single-member groups.

It's a bit confusing, but it works for me, and I haven't tried this latest solution you've posted because you posted midway through me writing this.  You get all the points, of course, because I couldn't have done this without you.
0
 
sirbountyCommented:
Glad you got it working.
The above will display the count of group members who are users, vs other groups, vs contacts, etc...

Thanks for the grade!
0
 
netjonAuthor Commented:
I wonder if it's because you had
i=0

Open in new window

instead of
Set i=0

Open in new window

?
0
 
sirbountyCommented:
No, that's not it.  you use set to instantiate an object.  i is an integer variable.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

  • 9
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now