Solved

exporting empty groups AD server 2003

Posted on 2013-11-13
16
262 Views
Last Modified: 2013-11-15
Hi,

I'd like to export all the empty groups in AD.  I have found the vb script below from a previous question.  I would like to know how to write the output to a text file?

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 Name,Member FROM 'LDAP://dc=rustice,dc=local' WHERE objectCategory='group'"
Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    If isNull(objRecordSet.Fields("Member").Value) Then
          Wscript.Echo objRecordSet.Fields("Name").Value
    End If
    objRecordSet.MoveNext
Loop
0
Comment
Question by:cmatchett
  • 9
  • 7
16 Comments
 
LVL 12

Expert Comment

by:piattnd
ID: 39645423
This link describes it pretty well, but I've included the code below.

http://www.activexperts.com/activmonitor/windowsmanagement/adminscripts/other/textfiles/#WriteDataText.htm

On Error Resume Next

Const ADS_SCOPE_SUBTREE = 2
'2 indicates you want to write to the file.  This will wipe out the contents of the file when you open it
Const ForWriting = 2

'Path to the log file.  Change this if you want
strLogFilePath = "C:\someLog.txt"

Set objFSO = CreateObject("Scripting.FileSystemObject")

'make sure the file exists, create it if it doesn't
if NOT objFSO.FileExists(strLogFilePath) then
    objFSO.CreateTextFile(strLogFilePath,true)
end if

'Open the log file so we can write to it
Set objLog = objFSO.OpenTextFile(strLogFilePath,ForWriting)

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 Name,Member FROM 'LDAP://dc=rustice,dc=local' WHERE objectCategory='group'"
Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    If isNull(objRecordSet.Fields("Member").Value) Then
          objLog.writeline(objRecordSet.Fields("Name").Value)
          'Wscript.Echo objRecordSet.Fields("Name").Value
    End If
    objRecordSet.MoveNext
Loop 

'close the log file
objLog.close

Open in new window


Let me know if you get any errors
0
 
LVL 12

Expert Comment

by:piattnd
ID: 39645424
Oh, make sure you comment out your On Error Resume Next, otherwise you won't be able to see if it errors on the log file portion (I didn't write in error handling).
0
 

Author Comment

by:cmatchett
ID: 39645488
does appear to create and write to the file
0
 

Author Comment

by:cmatchett
ID: 39645500
the error is...

Cannot use parentheses when calling a Sub
0
 

Author Comment

by:cmatchett
ID: 39645507
sorry my comment previously was meant to say that it did not create the text file and write to it
0
 
LVL 12

Accepted Solution

by:
piattnd earned 500 total points
ID: 39645548
Try this:

On Error Resume Next

Const ADS_SCOPE_SUBTREE = 2
'2 indicates you want to write to the file.  This will wipe out the contents of the file when you open it
Const ForWriting = 2

'Path to the log file.  Change this if you want
strLogFilePath = "C:\someLog.txt"

Set objFSO = CreateObject("Scripting.FileSystemObject")

'make sure the file exists, create it if it doesn't
if NOT objFSO.FileExists(strLogFilePath) then
    objFSO.CreateTextFile strLogFilePath,true
end if

'Open the log file so we can write to it
Set objLog = objFSO.OpenTextFile(strLogFilePath,ForWriting)

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 Name,Member FROM 'LDAP://dc=rustice,dc=local' WHERE objectCategory='group'"
Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    If isNull(objRecordSet.Fields("Member").Value) Then
          objLog.writeline objRecordSet.Fields("Name").Value
          'Wscript.Echo objRecordSet.Fields("Name").Value
    End If
    objRecordSet.MoveNext
Loop 

'close the log file
objLog.close

Open in new window

0
 

Author Comment

by:cmatchett
ID: 39646538
top stuff piattnd
0
 

Author Comment

by:cmatchett
ID: 39646548
How do i add further fields into it?  Like if i want the type of the group?
0
 
LVL 12

Expert Comment

by:piattnd
ID: 39646569
Hah, now you're getting into the nitty-gritty of how Microsoft stores stuff like that in Active Directory!  :)

See this link:

http://blogs.technet.com/b/heyscriptingguy/archive/2004/12/21/how-can-i-tell-whether-a-group-is-a-security-group-or-a-distribution-group.aspx

Basically, you'd need to change a few lines, starting with your query line:
objCommand.CommandText = _
    "SELECT Name,Member FROM 'LDAP://dc=rustice,dc=local' WHERE objectCategory='group'"

Open in new window

Change that to include the distinguishedName:
objCommand.CommandText = _
    "SELECT distinguishedName,Name,Member FROM 'LDAP://dc=rustice,dc=local' WHERE objectCategory='group'"

Open in new window

Now once you've found a group that is empty, get the type of group.  Here is the chunk of code as you have it:
    If isNull(objRecordSet.Fields("Member").Value) Then
          objLog.writeline objRecordSet.Fields("Name").Value
          'Wscript.Echo objRecordSet.Fields("Name").Value
    End If

Open in new window

Change that to:
    If isNull(objRecordSet.Fields("Member").Value) Then
          'grab the distinguishedName and throw it into a variable
          strGroupDN = objRecordSet.Fields("distinguishedName").Value
          'connect to that object so you can grab further attributes
          Set objGroup = GetObject(strGroupDN)
          'Set the strGroupType to unknown in case it doesn't match one of the below
          strGroupType = "unknown"
          'Using the code in the link, determine the group type and assign it to a variable
           Select Case objGroup.GroupType
           Case 2
                strGroupType = "global distro"
                'Wscript.Echo "This is a global distribution group."
           Case 4
                strGroupType = "local distro"
                'Wscript.Echo "This is a domain local distribution group."
           Case 8
                strGroupType = "universal distro"
                'Wscript.Echo "This is a universal distribution group."
           Case -2147483646
                strGroupType = "global security"
                'Wscript.Echo "This is a global security group."
           Case -2147483644
                strGroupType = "local security"
                'Wscript.Echo "This is a domain local security group."
          Case -2147483640
                strGroupType = "universal security"
                'Wscript.Echo "This is a universal security group."
          End Select

          objLog.writeline objRecordSet.Fields("Name").Value & " - GROUP TYPE: " & strGroupType
          'Wscript.Echo objRecordSet.Fields("Name").Value
    End If

Open in new window

That should do it for ya.  Let me know if you get any errors.
0
 

Author Comment

by:cmatchett
ID: 39646581
in these sections below, fields member and name is selected.  The evaluation is done on member and then the name is written to text file.  Could you not also SELECT TYPE, NAME, MEMBER and then write type and name to the log too?  I tried an extra line to write type but it didn't work

objCommand.CommandText = _
    "SELECT Name,Member FROM 'LDAP://dc=rustice,dc=local' WHERE objectCategory='group'"
Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst
Do Until objRecordSet.EOF
    If isNull(objRecordSet.Fields("Member").Value) Then
          objLog.writeline objRecordSet.Fields("Name").Value
          'Wscript.Echo objRecordSet.Fields("Name").Value
    End If
    objRecordSet.MoveNext
Loop
0
 
LVL 12

Expert Comment

by:piattnd
ID: 39646586
I posted all the code changes needed to accomplish this in my previous response.  You cannot grab additional attributes from a query that you didn't ask for.

For example, your query asks for "name" and "member".  You will only be given the values of "name" and "member" for each group matching your filter (all groups).  Some attributes are not indexed and not possible to grab through a query like that, so you have to connect directly to the object (see my code).  Once you are bound to the object, you can grab those attributes.
0
 

Author Comment

by:cmatchett
ID: 39646598
super stuff, i will try it in the morning.
0
 

Author Comment

by:cmatchett
ID: 39647351
Hi,

The output lists all groups as unknown.  The values match the values in ADSI edit
0
 
LVL 12

Expert Comment

by:piattnd
ID: 39647965
Put a wscript.echo right before the "select case..." statement to echo out the value of objGroup.GroupType.  Also echo the name of the group in there so you can compare the value it echos for GroupType to the actual type of group it is.
0
 
LVL 12

Expert Comment

by:piattnd
ID: 39647969
Oh, and if you put the On Error Resume Next back in, take that out.  You want to be notified if there's an error (or you need to code in error handling).
0
 

Author Comment

by:cmatchett
ID: 39650848
I got the group type using LDIFDE.  You were a great help super stuff
0

Join & Write a Comment

As network administrators; we know how hard it is to track user’s login/logout using security event log (BTW it is harder now in windows 2008 because user name is always “N/A” in the grid), and most of us either get 3rd party tools, or just make our…
Do you have users whose passwords are expiring and they are constantly calling you?  Well I sure did and needed a way to put an end to this.  We have a lot of remote users which would not be notified that their passwords were expiring since they wer…
This tutorial will walk an individual through the steps necessary to join and promote the first Windows Server 2012 domain controller into an Active Directory environment running on Windows Server 2008. Determine the location of the FSMO roles by lo…
This tutorial will walk an individual through the process of configuring their Windows Server 2012 domain controller to synchronize its time with a trusted, external resource. Use Google, Bing, or other preferred search engine to locate trusted NTP …

760 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

20 Experts available now in Live!

Get 1:1 Help Now