Re: Enumerate Empty Global Groups
From: Shaun Sawyer (anonymous_at_discussions.microsoft.com)
Date: 04/26/04
- Next message: Richard Mueller [MVP]: "Re: Enumerate Empty Global Groups"
- Previous message: Ken: "RE: How we write the results of script into an OS text file ?"
- In reply to: Richard Mueller [MVP]: "Re: Enumerate Empty Global Groups"
- Next in thread: Richard Mueller [MVP]: "Re: Enumerate Empty Global Groups"
- Reply: Richard Mueller [MVP]: "Re: Enumerate Empty Global Groups"
- Messages sorted by: [ date ] [ thread ]
Date: Mon, 26 Apr 2004 12:06:01 -0700
Hi Richard,
Many thanks for your efforts (especially if you started this one from scratch!), the script produced the exact results that I needed.
May all questions posted to this newsgroup receive a similar professional responce...
Kind regards,
Shaun
----- Richard Mueller [MVP] wrote: -----
"Richard Mueller [MVP]" <rlmueller-NOSPAM@ameritech.NOSPAM.net> wrote in
message news:eshm9m6KEHA.4052@TK2MSFTNGP11.phx.gbl...
> Shaun Sawyer wrote:
>>> I am new to this group so please forgive me if the question has been
asked
> before. We have recently restructure and I want to audit all group
> membership. Is there a simple script for enumerating all Global Groups
> within the domain (regardless of OU) that no longer have any members?
>> Hi,
>> Actually, this is a tricky question. You can use ADO to retrieve all
groups
> where the member attribute is empty. However, the member attribute does
not
> include any users that have the group designated as their "primary" group.
> By default, all user objects have the group "Domain Users" designated as
> their "primary group", and all computer objects have "Domain Computers" as
> their "primary" group. These defaults should not be changed. If they have
> not, you can use the script below. For example, the groups "Domain Users"
> and "Domain Computers" may show up as empty, but that may just mean that
all
> of their members have the group as their "primary" group.
>> Option Explicit
> Dim objRootDSE, strDNSDomain, objCommand, objConnection
> Dim strBase, strFilter, strAttributes, strQuery, objRecordSet
> Dim strNTName
>> ' Determine DNS domain name.
> Set objRootDSE = GetObject("LDAP://RootDSE")
> strDNSDomain = objRootDSE.Get("defaultNamingContext")
>> ' Use ADO to search Active Directory.
> Set objCommand = CreateObject("ADODB.Command")
> Set objConnection = CreateObject("ADODB.Connection")
> objConnection.Provider = "ADsDSOObject"
> objConnection.Open "Active Directory Provider"
> objCommand.ActiveConnection = objConnection
> strBase = "<LDAP://" & strDNSDomain & ">"
>> strFilter = "(&(objectCategory=group)(!(member=*)))"
> strAttributes = "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
> strNTName = objRecordSet.Fields("sAMAccountName")
> Wscript.Echo "Group with no members: " & strNTName
> objRecordSet.MoveNext
> Loop
>> In the filter clause, the "!" means "Not" and "*" is a wildcard. The
clause
> "(!(member=*))" means where the member attribute is empty (not equal to
> anything). The "member" attribute is a multivalued collection of member
> distinguished names. The "sAMAccountName" attribute is the NT user name,
> also called the "pre-Windows 2000 logon name". The above can be used, if
you
> remember that any groups listed will not truely be empty if they have
> "primary" group members. I'll have to think how to improve this so it
lists
> groups that are really empty.
>> --
> Richard
> Microsoft MVP Scripting and ADSI
> HilltopLab web site - http://www.rlmueller.net
> --
Hi,
The script below lists all groups in the domain that are empty. I use the
same procedure as before, using ADO to retrieve all groups where the
"member" attribute is empty. However, besides the group name I retrieve the
value of the primaryGroupToken attribute. I put the values into a dynamic
array. I also construct a filter for another ADO search. This time I look
for any objects whose "primaryGroupID" attribute matches any of the values
for "primaryGroupToken" just retrieved. I search for any object of any class
(user, computer, group, whatever) that has any of the first collection of
groups designated as their "primary" group. I use a dictionary object to
keep track of which groups are thereby not truely empty. Finally, I
enumerate the first collection of groups and only output the names of those
that are not in the dictionary object. Below is the script:
Option Explicit
Dim objRootDSE, strDNSDomain, objCommand, objConnection
Dim strBase, strFilter, strAttributes, strQuery, objRecordSet
Dim strNTName, lngPriGrpToken, arrstrGroups(), k
Dim objGroupList
Set objGroupList = CreateObject("Scripting.Dictionary")
' Determine DNS domain name.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
' Use ADO to search Active Directory.
Set objCommand = CreateObject("ADODB.Command")
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection
strBase = "<LDAP://" & strDNSDomain & ">"
strFilter = "(&(objectCategory=group)(!(member=*)))"
strAttributes = "sAMAccountName,primaryGroupToken"
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
k = 0
strFilter = "(|"
Do Until objRecordSet.EOF
strNTName = objRecordSet.Fields("sAMAccountName")
lngPriGrpToken = objRecordSet.Fields("primaryGroupToken")
ReDim Preserve arrstrGroups(1, k)
arrstrGroups(0, k) = strNTName
arrstrGroups(1, k) = lngPriGrpToken
strFilter = strFilter & "(primaryGroupID=" & lngPriGrpToken & ")"
k = k + 1
objRecordSet.MoveNext
Loop
strFilter = strFilter & ")"
If strFilter = "(|)" Then
Wscript.Echo "No empty groups found"
Wscript.Quit
End If
strAttributes = "sAMAccountName,primaryGroupID"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
objCommand.CommandText = strQuery
Set objRecordSet = objCommand.Execute
Do Until objRecordSet.EOF
strNTName = objRecordSet.Fields("sAMAccountName")
lngPriGrpToken = objRecordSet.Fields("primaryGroupID")
If Not objGroupList.Exists(lngPriGrpToken) Then
objGroupList(lngPriGrpToken) = True
End If
objRecordSet.MoveNext
Loop
For k = 0 To UBound(arrstrGroups, 2)
If Not objGroupList.Exists(arrstrGroups(1, k)) Then
Wscript.Echo "Group with no members: " & arrstrGroups(0, k)
End If
Next
--
Richard
Microsoft MVP Scripting and ADSI
HilltopLab web site - http://www.rlmueller.net
--
- Next message: Richard Mueller [MVP]: "Re: Enumerate Empty Global Groups"
- Previous message: Ken: "RE: How we write the results of script into an OS text file ?"
- In reply to: Richard Mueller [MVP]: "Re: Enumerate Empty Global Groups"
- Next in thread: Richard Mueller [MVP]: "Re: Enumerate Empty Global Groups"
- Reply: Richard Mueller [MVP]: "Re: Enumerate Empty Global Groups"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|