seaninman
asked on
Modify VB Script to also pull in Security Group Memberships
I was wondering if someone could help me add some code to this script to output the security groups associated to each user as well as what is already being outputted.
'Define Constants
Const ForReading = 1
Const ADS_SCOPE_SUBTREE = 2 ' Search target object and all sub levels
Const ADS_GROUP_TYPE_SECURITY_ENABLED = &H80000000
DQ = Chr(34) 'Double Quote
WScript.Echo "Creating user file"
'Create Objects
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set SecurityGroups = CreateObject("System.Collections.ArrayList")
Set DistributionGroups = CreateObject("System.Collections.ArrayList")
'Construct an ADsPath to the Current Domain with rootDSE
Set objRootDSE = GetObject("LDAP://rootDSE")
strADsPath = "LDAP://" & objRootDSE.Get("defaultNamingContext")
'Connect to Active Directory
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
'Create output text file
strScriptPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
strOutputFilePath = strScriptPath & "users.txt"
Set objOutputFile = objFSO.CreateTextFile(strOutputFilePath)
'Search AD for user
objCommand.CommandText = _
"SELECT ADsPath FROM '" & strADsPath & _
"' WHERE objectCategory='user'"
Set objRecordSet = objCommand.Execute
'Verify user was found
If objRecordSet.EOF Then
WScript.echo "No users were found."
Else
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
strUserADsPath = objRecordSet.Fields("ADsPath").Value
'Connect to user account
Set objUser = GetObject(strUserADsPath)
'Format Last Logon Time Stamp
'Set objLastLogon=null
dtmLastLogon=""
on error resume next
Set objLastLogon = objUser.Get("lastLogonTimestamp")
if not isNull(objLastLogon) then
intLastLogonTime = objLastLogon.HighPart * (2 ^ 32) + objLastLogon.LowPart
intLastLogonTime = intLastLogonTime / (60 * 10000000)
intLastLogonTime = intLastLogonTime / 1440
dtmLastLogon = intLastLogonTime + # 1 / 1 / 1601 #
end if
on error goto 0
'Populate text file
ws=DQ & objUser.sAMAccountName & DQ
ws=ws & "," & DQ & objUser.extensionAttribute1 & DQ
ws=ws & "," & DQ & objUser.description & DQ
ws=ws & "," & DQ & objUser.whenCreated & DQ
ws=ws & "," & DQ & dtmLastLogon & DQ
ws=ws & "," & DQ & objUser.mail & DQ
ws=ws & "," & DQ & objUser.info & DQ
objOutputFile.WriteLine ws
objRecordSet.MoveNext
Loop
End If
WScript.Echo "Finished creating file"
objOutputFile.Close
'Open file
strOpenFile = MsgBox("Do you want to open the output file?", VbYesNo + VBQuestion, "Open Output File?")
If strOpenFile = VbYes Then
objShell.Run("notepad.exe " & DQ & strOutputFilePath & DQ)
End If
ASKER
The script fails on
Line 80
Char 6
Error 0x80005000
Code 80005000
Source (null)
Line 80
Char 6
Error 0x80005000
Code 80005000
Source (null)
That's odd....it works for me....I wonder if your group names have characters that need escaping?
Run this from a command prompt with
cscript GetUsers.vbs
and see what group DN is crashes on.
Regards,
Rob.
Run this from a command prompt with
cscript GetUsers.vbs
and see what group DN is crashes on.
Regards,
Rob.
'Define Constants
Const ForReading = 1
Const ADS_SCOPE_SUBTREE = 2 ' Search target object and all sub levels
Const ADS_GROUP_TYPE_SECURITY_ENABLED = &H80000000
DQ = Chr(34) 'Double Quote
WScript.Echo "Creating user file"
'Create Objects
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Construct an ADsPath to the Current Domain with rootDSE
Set objRootDSE = GetObject("LDAP://rootDSE")
strADsPath = "LDAP://" & objRootDSE.Get("defaultNamingContext")
'Connect to Active Directory
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
'Create output text file
strScriptPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
strOutputFilePath = strScriptPath & "users.txt"
Set objOutputFile = objFSO.CreateTextFile(strOutputFilePath)
'Search AD for user
objCommand.CommandText = _
"SELECT ADsPath FROM '" & strADsPath & _
"' WHERE objectCategory='user'"
Set objRecordSet = objCommand.Execute
'Verify user was found
If objRecordSet.EOF Then
WScript.echo "No users were found."
Else
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
strUserADsPath = objRecordSet.Fields("ADsPath").Value
'Connect to user account
Set objUser = GetObject(strUserADsPath)
'Format Last Logon Time Stamp
'Set objLastLogon=Null
dtmLastLogon=""
on error resume Next
Set objLastLogon = objUser.Get("lastLogonTimestamp")
if not isNull(objLastLogon) then
intLastLogonTime = objLastLogon.HighPart * (2 ^ 32) + objLastLogon.LowPart
intLastLogonTime = intLastLogonTime / (60 * 10000000)
intLastLogonTime = intLastLogonTime / 1440
dtmLastLogon = intLastLogonTime + # 1 / 1 / 1601 #
end If
on error goto 0
'Populate text file
ws=DQ & objUser.sAMAccountName & DQ
'ws=ws & "," & DQ & objUser.extensionAttribute1 & DQ
ws=ws & "," & DQ & " " & DQ
ws=ws & "," & DQ & objUser.description & DQ
ws=ws & "," & DQ & objUser.whenCreated & DQ
ws=ws & "," & DQ & dtmLastLogon & DQ
ws=ws & "," & DQ & objUser.mail & DQ
ws=ws & "," & DQ & objUser.info & DQ
strGroups = ""
If TypeName(objUser.MemberOf) <> "Empty" Then
If TypeName(objUser.MemberOf) = "String" Then
Set objGroup = GetObject("LDAP://" & objUser.MemberOf)
strGroups = Mid(objGroup.Name, 4)
Else
For Each strGroupDN In objUser.MemberOf
WScript.Echo Mid(objUser.Name, 4) & ": Group membership - " & strGroupDN
Set objGroup = GetObject("LDAP://" & strGroupDN)
If strGroups = "" Then
strGroups = Mid(objGroup.Name, 4)
Else
strGroups = strGroups & "," & Mid(objGroup.Name, 4)
End If
Next
End If
End If
ws=ws & "," & DQ & strGroups & DQ
objOutputFile.WriteLine ws
objRecordSet.MoveNext
Loop
End If
WScript.Echo "Finished creating file"
objOutputFile.Close
'Open file
strOpenFile = MsgBox("Do you want to open the output file?", VbYesNo + VBQuestion, "Open Output File?")
If strOpenFile = VbYes Then
objShell.Run("notepad.exe " & DQ & strOutputFilePath & DQ)
End If
ASKER
I ran the script like you said and it has populated some data. Â How do I tell what group it's failing on?
If it has an error, it should be the last message in the command prompt, since we're not using On Error Resume Next, so it just terminate the script at that point, and show the error in the command prompt.
If it doesn't error, then that means you should have all your data.
Rob.
If it doesn't error, then that means you should have all your data.
Rob.
ASKER
In the command prompt window, there is output data on a few users, but the output txt file it creates doesn't contain all the users. Â So is the issues with the data that is outputted in the command prompt window?
Thanks
Thanks
How many users are showing in the text file? Â Is it 1000? Â There might be a record limit from the AD query....
Does it still produce an error though? Â If not, I don't see any reason why it wouldn't output all of your users....
Does it still produce an error though? Â If not, I don't see any reason why it wouldn't output all of your users....
ASKER
There are only 158 users in the text file and it doesn't show all the security groups for those users. Â
There are only 14 users in the command prompt window, however there are multiple lines for those 14 users that has the [username: Group Membership - (Group Name)
There is still an error and it is: C:\temp\getusers.vbs(82, 6) (null): 0x80005000
You mentioned a query limit. Â I do have over 40,000 users. Â Should we try altering the script to only do specific OU's instead of all user objects?
There are only 14 users in the command prompt window, however there are multiple lines for those 14 users that has the [username: Group Membership - (Group Name)
There is still an error and it is: C:\temp\getusers.vbs(82, 6) (null): 0x80005000
You mentioned a query limit. Â I do have over 40,000 users. Â Should we try altering the script to only do specific OU's instead of all user objects?
I assume line 82 in your script is this one:
                                 strGroups = Mid(objGroup.Name, 4)
and *not* this one:
                            Set objGroup = GetObject("LDAP://" & strGroupDN)
which is the one I orginally thought it was when you said the error was on line 80. Â The one with Mid actually makes more sense to have an error, so I've changed that to output the CN, instead of Name. Â I guess it *might* be possible that a group doesn't have a "name", but they MUST have a CN, so we'll try that.
If you're not already using a script editor, grab VBSEdit so you can see line numbers.
And wow....40,000 users....this script will take a while! Â Make sure you run it with CScript, so it will give you some output.
Regards,
Rob.
                                 strGroups = Mid(objGroup.Name, 4)
and *not* this one:
                            Set objGroup = GetObject("LDAP://" & strGroupDN)
which is the one I orginally thought it was when you said the error was on line 80. Â The one with Mid actually makes more sense to have an error, so I've changed that to output the CN, instead of Name. Â I guess it *might* be possible that a group doesn't have a "name", but they MUST have a CN, so we'll try that.
If you're not already using a script editor, grab VBSEdit so you can see line numbers.
And wow....40,000 users....this script will take a while! Â Make sure you run it with CScript, so it will give you some output.
Regards,
Rob.
'Define Constants
Const ForReading = 1
Const ADS_SCOPE_SUBTREE = 2 ' Search target object and all sub levels
Const ADS_GROUP_TYPE_SECURITY_ENABLED = &H80000000
DQ = Chr(34) 'Double Quote
WScript.Echo "Creating user file"
'Create Objects
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Construct an ADsPath to the Current Domain with rootDSE
Set objRootDSE = GetObject("LDAP://rootDSE")
strADsPath = "LDAP://" & objRootDSE.Get("defaultNamingContext")
'Connect to Active Directory
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
'Create output text file
strScriptPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
strOutputFilePath = strScriptPath & "users.txt"
Set objOutputFile = objFSO.CreateTextFile(strOutputFilePath)
'Search AD for user
objCommand.CommandText = _
"SELECT ADsPath FROM '" & strADsPath & _
"' WHERE objectCategory='user'"
Set objRecordSet = objCommand.Execute
'Verify user was found
If objRecordSet.EOF Then
WScript.echo "No users were found."
Else
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
strUserADsPath = objRecordSet.Fields("ADsPath").Value
'Connect to user account
Set objUser = GetObject(strUserADsPath)
'Format Last Logon Time Stamp
'Set objLastLogon=Null
dtmLastLogon=""
on error resume Next
Set objLastLogon = objUser.Get("lastLogonTimestamp")
if not isNull(objLastLogon) then
intLastLogonTime = objLastLogon.HighPart * (2 ^ 32) + objLastLogon.LowPart
intLastLogonTime = intLastLogonTime / (60 * 10000000)
intLastLogonTime = intLastLogonTime / 1440
dtmLastLogon = intLastLogonTime + # 1 / 1 / 1601 #
end If
on error goto 0
'Populate text file
ws=DQ & objUser.sAMAccountName & DQ
'ws=ws & "," & DQ & objUser.extensionAttribute1 & DQ
ws=ws & "," & DQ & " " & DQ
ws=ws & "," & DQ & objUser.description & DQ
ws=ws & "," & DQ & objUser.whenCreated & DQ
ws=ws & "," & DQ & dtmLastLogon & DQ
ws=ws & "," & DQ & objUser.mail & DQ
ws=ws & "," & DQ & objUser.info & DQ
WScript.Echo "Enumerating group membership of " & objUser.CN
strGroups = ""
If TypeName(objUser.MemberOf) <> "Empty" Then
If TypeName(objUser.MemberOf) = "String" Then
Set objGroup = GetObject("LDAP://" & objUser.MemberOf)
strGroups = objGroup.CN
Else
For Each strGroupDN In objUser.MemberOf
Set objGroup = GetObject("LDAP://" & strGroupDN)
If strGroups = "" Then
strGroups = objGroup.CN
Else
strGroups = strGroups & "," & objGroup.CN
End If
Next
End If
End If
ws=ws & "," & DQ & strGroups & DQ
objOutputFile.WriteLine ws
objRecordSet.MoveNext
Loop
End If
WScript.Echo "Finished creating file"
objOutputFile.Close
'Open file
strOpenFile = MsgBox("Do you want to open the output file?", VbYesNo + VBQuestion, "Open Output File?")
If strOpenFile = VbYes Then
objShell.Run("notepad.exe " & DQ & strOutputFilePath & DQ)
End If
ASKER
I am still getting that error message and in the text file it only outputs about 159 users and their information.
Hmm. Â Try changing the If block to this:
Then run it using CScript again. Â When it errors this time (if it does), look in the command prompt for the last "Binding to" output, and post that DN here....I suspect there's some characters we need to escape.
Regards,
Rob.
If TypeName(objUser.MemberOf) <> "Empty" Then
If TypeName(objUser.MemberOf) = "String" Then
WScript.Echo "Binding to " & objUser.MemberOf
Set objGroup = GetObject("LDAP://" & Replace(Replace(Replace(objUser.MemberOf, "\", "\\"), "/", "\/"))
strGroups = objGroup.CN
Else
For Each strGroupDN In objUser.MemberOf
WScript.Echo "Binding to " & strGroupDN
Set objGroup = GetObject("LDAP://" & Replace(Replace(Replace(strGroupDN, "\", "\\"), "/", "\/"))
If strGroups = "" Then
strGroups = objGroup.CN
Else
strGroups = strGroups & "," & objGroup.CN
End If
Next
End If
End If
Then run it using CScript again. Â When it errors this time (if it does), look in the command prompt for the last "Binding to" output, and post that DN here....I suspect there's some characters we need to escape.
Regards,
Rob.
Sorry, I didn't have my script editor with me....I had one too many Replace statements. Â Try this.
Rob.
Rob.
'Define Constants
Const ForReading = 1
Const ADS_SCOPE_SUBTREE = 2 ' Search target object and all sub levels
Const ADS_GROUP_TYPE_SECURITY_ENABLED = &H80000000
DQ = Chr(34) 'Double Quote
WScript.Echo "Creating user file"
'Create Objects
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Construct an ADsPath to the Current Domain with rootDSE
Set objRootDSE = GetObject("LDAP://rootDSE")
strADsPath = "LDAP://" & objRootDSE.Get("defaultNamingContext")
'Connect to Active Directory
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
'Create output text file
strScriptPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
strOutputFilePath = strScriptPath & "users.txt"
Set objOutputFile = objFSO.CreateTextFile(strOutputFilePath)
'Search AD for user
objCommand.CommandText = _
"SELECT ADsPath FROM '" & strADsPath & _
"' WHERE objectCategory='user'"
Set objRecordSet = objCommand.Execute
'Verify user was found
If objRecordSet.EOF Then
WScript.echo "No users were found."
Else
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
strUserADsPath = objRecordSet.Fields("ADsPath").Value
'Connect to user account
Set objUser = GetObject(strUserADsPath)
'Format Last Logon Time Stamp
'Set objLastLogon=Null
dtmLastLogon=""
on error resume Next
Set objLastLogon = objUser.Get("lastLogonTimestamp")
if not isNull(objLastLogon) then
intLastLogonTime = objLastLogon.HighPart * (2 ^ 32) + objLastLogon.LowPart
intLastLogonTime = intLastLogonTime / (60 * 10000000)
intLastLogonTime = intLastLogonTime / 1440
dtmLastLogon = intLastLogonTime + # 1 / 1 / 1601 #
end If
on error goto 0
'Populate text file
ws=DQ & objUser.sAMAccountName & DQ
'ws=ws & "," & DQ & objUser.extensionAttribute1 & DQ
ws=ws & "," & DQ & " " & DQ
ws=ws & "," & DQ & objUser.description & DQ
ws=ws & "," & DQ & objUser.whenCreated & DQ
ws=ws & "," & DQ & dtmLastLogon & DQ
ws=ws & "," & DQ & objUser.mail & DQ
ws=ws & "," & DQ & objUser.info & DQ
WScript.Echo "Enumerating group membership of " & objUser.CN
strGroups = ""
If TypeName(objUser.MemberOf) <> "Empty" Then
If TypeName(objUser.MemberOf) = "String" Then
WScript.Echo "Binding to " & objUser.MemberOf
Set objGroup = GetObject("LDAP://" & Replace(Replace(objUser.MemberOf, "\", "\\"), "/", "\/"))
strGroups = objGroup.CN
Else
For Each strGroupDN In objUser.MemberOf
WScript.Echo "Binding to " & strGroupDN
Set objGroup = GetObject("LDAP://" & Replace(Replace(strGroupDN, "\", "\\"), "/", "\/"))
If strGroups = "" Then
strGroups = objGroup.CN
Else
strGroups = strGroups & "," & objGroup.CN
End If
Next
End If
End If
ws=ws & "," & DQ & strGroups & DQ
objOutputFile.WriteLine ws
objRecordSet.MoveNext
Loop
End If
WScript.Echo "Finished creating file"
objOutputFile.Close
'Open file
strOpenFile = MsgBox("Do you want to open the output file?", VbYesNo + VBQuestion, "Open Output File?")
If strOpenFile = VbYes Then
objShell.Run("notepad.exe " & DQ & strOutputFilePath & DQ)
End If
ASKER
Hmmm, I think it was some weird way the string of the DN was being evaluated. Â I have created a group with the same CN, made a small change, and now it works. Â See how this goes for you now.
Regards,
Rob.
Regards,
Rob.
'Define Constants
Const ForReading = 1
Const ADS_SCOPE_SUBTREE = 2 ' Search target object and all sub levels
Const ADS_GROUP_TYPE_SECURITY_ENABLED = &H80000000
DQ = Chr(34) 'Double Quote
WScript.Echo "Creating user file"
'Create Objects
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Construct an ADsPath to the Current Domain with rootDSE
Set objRootDSE = GetObject("LDAP://rootDSE")
strADsPath = "LDAP://" & objRootDSE.Get("defaultNamingContext")
'Connect to Active Directory
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
'Create output text file
strScriptPath = Replace(WScript.ScriptFullName, WScript.ScriptName, "")
strOutputFilePath = strScriptPath & "users.txt"
Set objOutputFile = objFSO.CreateTextFile(strOutputFilePath)
'Search AD for user
objCommand.CommandText = _
"SELECT ADsPath FROM '" & strADsPath & _
"' WHERE objectCategory='user'"
Set objRecordSet = objCommand.Execute
'Verify user was found
If objRecordSet.EOF Then
WScript.echo "No users were found."
Else
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
strUserADsPath = objRecordSet.Fields("ADsPath").Value
'Connect to user account
Set objUser = GetObject(strUserADsPath)
'Format Last Logon Time Stamp
'Set objLastLogon=Null
dtmLastLogon=""
on error resume Next
Set objLastLogon = objUser.Get("lastLogonTimestamp")
if not isNull(objLastLogon) then
intLastLogonTime = objLastLogon.HighPart * (2 ^ 32) + objLastLogon.LowPart
intLastLogonTime = intLastLogonTime / (60 * 10000000)
intLastLogonTime = intLastLogonTime / 1440
dtmLastLogon = intLastLogonTime + # 1 / 1 / 1601 #
end If
on error goto 0
'Populate text file
ws=DQ & objUser.sAMAccountName & DQ
'ws=ws & "," & DQ & objUser.extensionAttribute1 & DQ
ws=ws & "," & DQ & " " & DQ
ws=ws & "," & DQ & objUser.description & DQ
ws=ws & "," & DQ & objUser.whenCreated & DQ
ws=ws & "," & DQ & dtmLastLogon & DQ
ws=ws & "," & DQ & objUser.mail & DQ
ws=ws & "," & DQ & objUser.info & DQ
WScript.Echo "Enumerating group membership of " & objUser.CN
strGroups = ""
If TypeName(objUser.MemberOf) <> "Empty" Then
If TypeName(objUser.MemberOf) = "String" Then
strADsPath = "LDAP://" & objUser.MemberOf
WScript.Echo "Binding to " & strADsPath
Set objGroup = GetObject(strADsPath)
strGroups = objGroup.CN
Else
For Each strGroupDN In objUser.MemberOf
strADsPath = "LDAP://" & strGroupDN
WScript.Echo "Binding to " & strADsPath
Set objGroup = GetObject(strADsPath)
If strGroups = "" Then
strGroups = objGroup.CN
Else
strGroups = strGroups & "," & objGroup.CN
End If
Next
End If
End If
ws=ws & "," & DQ & strGroups & DQ
objOutputFile.WriteLine ws
objRecordSet.MoveNext
Loop
End If
WScript.Echo "Finished creating file"
objOutputFile.Close
'Open file
strOpenFile = MsgBox("Do you want to open the output file?", VbYesNo + VBQuestion, "Open Output File?")
If strOpenFile = VbYes Then
objShell.Run("notepad.exe " & DQ & strOutputFilePath & DQ)
End If
ASKER
Now the error is on line 84 column 6. Â
If you know and easy way to specify a specific an OU, I can do this by OU as my users are separated by OU, and then I can run it on different OU's until I find the user account(s) or Group(s) causing the issue.
If you know and easy way to specify a specific an OU, I can do this by OU as my users are separated by OU, and then I can run it on different OU's until I find the user account(s) or Group(s) causing the issue.
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
Regards,
Rob.
Open in new window