Solved

Script to list number of members of groups in ADAM

Posted on 2009-05-13
8
767 Views
Last Modified: 2012-05-06
Hi all,

I need to modify this AD script that provides a count of number of members of every group - so that it will work with an ADAM instance. I need the same formatted output, so that I can do a compare of the two txt files.

START/

'This script finds all groups in an AD, counts all members of each group
' and writes group names and count into a file
'*** will only count users in a group, will not count nested groups ****

Const ForAppending = 8
strSoeg = "SELECT Name FROM 'LDAP://dc=x, dc=y, dc=COM' " & _
    "WHERE objectCategory='group'" ' define domain to search
strDC = "DChostname" ' define Domain controler to lookup groups
strPath = "C:\Documents and Settings\mnewman\Desktop\ADvADAM\AD_Groups.csv" ' define file to write info

'Prepare file
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
    (strPath, ForAppending, True)

'Prepare for AD search

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") = 10

objCommand.CommandText = strSoeg

Set objRecordSet = objCommand.Execute

objRecordSet.Movefirst

Do until objRecordSet.EOF
    intMembers = 0
    'find group name
    strADsPath = objRecordSet.Fields("Name").value
    ' clean up group name
    strGroup = rtrim(ltrim(strADsPath))

    'prepare to access group strGroup
    Set objGroupe = GetObject("WinNT://" & strDC & "/" & strGroup & ",group")

    'count members of group strGroup
    For Each objMember in objGroupe.Members
        intMembers = intMembers + 1
    Next
    'write groupname and count to file
    objTextFile.WriteLine (strGroup & ";" & intMembers )
    set objGroupe = nothing
     objRecordSet.MoveNext

loop

'clean up
set objRecordSet = nothing
set objGroupe = nothing
set objTextFile = nothing
set objConnection = nothing
set objCommand = nothing
set objFSO = nothing

/END
0
Comment
Question by:dingo2045
  • 4
  • 4
8 Comments
 
LVL 12

Expert Comment

by:Krys_K
ID: 24436001
Hi there
I think all you need to do is amend the search string as follows:
strSoeg = "SELECT Name FROM 'LDAP://localhost:389/dc=x, dc=y, dc=COM' " & _
    "WHERE objectCategory='group'" ' define domain to search
What we are doing is directing the search to use the ADAM instance on the local computer (assuming that is where the ADAM instance is located) and passing the port number of ADAM which is the same as AD anyway
 
Hope that helps
Regards
Krystian
0
 

Author Comment

by:dingo2045
ID: 24436274
Krys,

Thanks for the reply.

I tried that, and the output shows a value of 1 for each group...as though it is unable to read the members and returns a value of 1 due to the loop in the script.

It seems to connect to the instance correctly but is unable to enumerate.

Thanks,
Mark
0
 
LVL 12

Expert Comment

by:Krys_K
ID: 24437260
Hi there
looking at your code, did you use the WinNT part once you had bound to the group in ADAM??
I think this would need to be amended also to use the Localhost and port number too!?
Regards
Krystian
0
 

Author Comment

by:dingo2045
ID: 24441089
Krys,

I have this set on the 4th line of code I have defined strDC as follows...

strDC = "localhost:389" ' define Domain controler to lookup groups

Then i modified the winNT section to show...

'prepare to access group strGroup
    Set objGroupe = GetObject("LDAP://" & strDC & "/" & strGroup & ",group")

    'count members of group strGroup
    For Each objMember in objGroupe.Member
        intMembers = intMembers + 1

I am sure it is this section where the issue is, as the output will correctkly list all groups (just a member count of 1, for each one).

What about objMember...doesn't this have to be defined (set) somewhere?

Thanks for the help.
Mark
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 12

Expert Comment

by:Krys_K
ID: 24446441
Hi There
Couple of things to note:
This line
strSoeg = "SELECT Name FROM 'LDAP://dc=x, dc=y, dc=COM' " & _
    "WHERE objectCategory='group'" ' define domain to search
Needs to be
strSoeg = "SELECT ADsPath FROM 'LDAP://dc=x, dc=y, dc=COM' " & _
    "WHERE objectCategory='group'" ' define domain to search
 
This line
strADsPath = objRecordSet.Fields("Name").value
Needs to be
strADsPath = objRecordSet.Fields("ADsPath").value
 which is returning the group in the form of LDAP://CN=GroupName,OU=MyLocation,DC=X,DC=Y,DC+COM
 
You dont need this line anymore:
strGroup = rtrim(ltrim(strADsPath))
 
This line
Set objGroupe = GetObject("WinNT://" & strDC & "/" & strGroup & ",group")
Needs to be
Set objGroupe = GetObject(strADsPath)
 
The rest should be OK. Just continue to use the LocalHost:389 as you were and all should be ok.
 
Hope that sorts it out for you.
Regards
Krystian
0
 

Author Comment

by:dingo2045
ID: 24451036
Krys,

I made these modifications. Now I get an output file that contains simply ";1"  , repeated indefinitly (until I end the process).

Mark
0
 
LVL 12

Expert Comment

by:Krys_K
ID: 24453001
Hi there
OK, i have re-written the script you gave me and tested it on my Server. I get the desired output correctly albeit on a Domain Controller. Theoretically, its no different with ADAM and all you are doing is forcing it to look on the ADAM server by using the LocalHost:389
 
I don't have an ADAM instance to play with so i can only hope that this will work for you
Regards
Krystian

	Const ForAppending = 8

	

	strSoeg = "SELECT Name, ADsPath FROM 'LDAP://dc=X,dc=Y' WHERE objectCategory='group'" ' define domain to search

	strDC = "localhost:389" ' define Domain controler to lookup groups

	strPath = "C:\Documents and Settings\mnewman\Desktop\ADvADAM\AD_Groups.csv" ' define file to write info

	

'Prepare file

	Set objFSO = CreateObject("Scripting.FileSystemObject")

	Set objTextFile = objFSO.OpenTextFile(strPath, ForAppending, True)

	

'Prepare for AD search

	

	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") = 10

		objCommand.CommandText = strSoeg

	

	Set objRecordSet = objCommand.Execute

	

		objRecordSet.Movefirst
 

	

	Do until objRecordSet.EOF

	    intMembers = 0
 

	    'find group name

	    strGroup = objRecordSet.Fields("Name")

	    strADsPath = objRecordSet.Fields("ADsPath")

	

	    'prepare to access group strGroup

	    Set objGroupe = GetObject(strADsPath)

	

	    'count members of group strGroup

	    For Each objMember in objGroupe.Members

	        ShowProgress objMember.Name

	        intMembers = intMembers + 1 

	    Next
 

	    'write groupname and count to file

	    objTextFile.WriteLine (strGroup & ";" & intMembers )
 

	    set objGroupe = Nothing
 

	     objRecordSet.MoveNext

	

	loop

	

'clean up

	Set objRecordSet = Nothing

	Set objGroupe = Nothing

	Set objTextFile = Nothing

	Set objConnection = Nothing

	Set objCommand = Nothing

	Set objFSO = Nothing

	

Open in new window

0
 

Accepted Solution

by:
dingo2045 earned 0 total points
ID: 24667004
Got this to work in the end. Here is the script that worked.
'This script finds all groups in an AD, counts all members of each group

' and writes group names and count into a file

'*** will only count users in a group, will not count nested groups ****
 

Const ForAppending = 8
 

'strDC value should be the server name of the ADAM instance, e.g. SERVER1

strDC = "server1" ' define Domain controler to lookup groups
 

'MS: The next line is the path to the output file...change it accordingly.

strPath = "C:\.......ADAM_Groups.csv" ' define file to write info
 

'Prepare file

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objTextFile = objFSO.OpenTextFile _

    (strPath, ForAppending, True)
 

'Prepare for AD search
 

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
 
 

strBase = "<LDAP://" & strDC & "/DC=x,DC=y,DC=z" & ">"

strFilter = "(&(objectClass=group))"

strAttributes = "name,distinguishedName,member,sAMAccountName"

strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
 

objCommand.CommandText = strQuery

objCommand.Properties("Page Size") = 100

objCommand.Properties("Timeout") = 30

'objCommand.Properties("Cache Results") = False
 

Set objRecordSet = objCommand.Execute
 

Do until objRecordSet.EOF

    intMembers = 0

    'find group name

    strName = objRecordSet.Fields("Name")

	

	'MS: Adding next line to get distinguishedName of each group.

	strDN = objRecordSet.Fields("distinguishedName")
 

	'MS: Adding next line to get members of each group

	strMEM = objRecordSet.Fields("member")
 

    'prepare to access group strGroup
 

	'MS: Changing next line to bind to the group properly so it can be enumerated properly.

    'Set objGroupe = GetObject("LDAP://" & strDN)
 

    'count members of group strGroup

	'MS: Changing the Member Enumeration to use the ADO recordset instead of binding to the group itself

	If Not IsNull(strMEM) And TypeName(strMEM) <> "String" Then

		For Each objMember in strMEM

			intMembers = intMembers + 1 

			wscript.echo objMember & " ; " & intMembers

		Next

	ElseIf Not IsNull(strMEM) And TypeName(strMEM) = "String" Then

		intMembers = intMembers + 1

		'wscript.echo objMember & " ; " & intMembers

	End If
 

    'write groupname and count to file

    objTextFile.WriteLine (strName & ";" & intMembers )

    'set objGroupe = Nothing

    

	'MS: Adding Line to make sure count resets

	intMembers = 0

     objRecordSet.MoveNext
 

Loop
 

objConnection.Close
 

'clean up

set objRecordSet = nothing

set objTextFile = nothing

set objConnection = nothing

set objCommand = nothing

set objFSO = nothing

Open in new window

0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Welcome to part one of a multi-part tutorial series, VBScript for Windows System Administrators.  The goal of this series is to teach non-programmers how to write useful VBS code to automate their environment, and perform tasks faster, and in a more…
I met Paul Devereux (@pdevereux) today when I responded to his tweet asking “Anybody know how to automate adding files from disk to a folder in #outlook  ?”.  I replied back and told Paul that using automation, in this case scripting, to add files t…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now