itsmevic
asked on
VB Script: Pull Active Users and Verify off Another Text File
Hi Experts,
I'm curious, if one of you guys/gals has a script that will go out to Active Directory and pull the sAMAccountNames of all Active Accoutns in two OU's within our Active Directory environment. The OU paths would be as such (I can fill those in): UserAccounts\xxx\xxx and UserAccounts\XXX OU trees. I'd then like to bounce the list of Active Users in AD against a a simple Master Text File that contains just the sAMAccountNames of Unix users. What the Script doesn't see in the Master Text File it would then note that in an output file (.csv file) Any help you can provide with this is GREATLY APPRECIATED!!!
I'm curious, if one of you guys/gals has a script that will go out to Active Directory and pull the sAMAccountNames of all Active Accoutns in two OU's within our Active Directory environment. The OU paths would be as such (I can fill those in): UserAccounts\xxx\xxx and UserAccounts\XXX OU trees. I'd then like to bounce the list of Active Users in AD against a a simple Master Text File that contains just the sAMAccountNames of Unix users. What the Script doesn't see in the Master Text File it would then note that in an output file (.csv file) Any help you can provide with this is GREATLY APPRECIATED!!!
Hi
Try this code. Run as cscript vbsfile> output.txt, output.txt will have the required info
Try this code. Run as cscript vbsfile> output.txt, output.txt will have the required info
' Get OU
'
strOU ="OU=UserAccounts,DC=domain,DC=com" 'UserAccounts\xxx\xxx
strOU2="OU=UserAccounts,DC=domain,DC=com"'UserAccounts\XXX
inputfile="c:\master.txt" 'unix user list
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile(inputfile, 1)
strreadall=objtextfile.ReadAll
' Create connection to AD
'
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
' Create command
'
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000
' Execute command to get all users in First OU
'
objCommand.CommandText = _
"<LDAP://" & strOU & ">;" & _
"(&(objectclass=user)(objectcategory=person));" & _
"sAMAccountName;subtree"
Set objRecordSet = objCommand.Execute
' Show info for each user in OU
'
Do Until objRecordSet.EOF
'WScript.Echo objRecordSet.Fields("sAMAccountName").Value
samname=objRecordSet.Fields("sAMAccountName").Value
If InStr(strreadall,samname)=0 Then
WScript.Echo samname & " - Not in Unix Master List"
End If
' Move to the next user
'
objRecordSet.MoveNext
Loop
objRecordSet.Close
' Execute command to get all users in Second OU
'
objCommand.CommandText = _
"<LDAP://" & strOU2 & ">;" & _
"(&(objectclass=user)(objectcategory=person));" & _
"sAMAccountName;subtree"
Set objRecordSet = objCommand.Execute
' Show info for each user in OU
'
Do Until objRecordSet.EOF
'WScript.Echo objRecordSet.Fields("sAMAccountName").Value
samname=objRecordSet.Fields("sAMAccountName").Value
If InStr(strreadall,samname)=0 Then
WScript.Echo samname & " - Not in Unix Master List"
End If
' Move to the next user
'
objRecordSet.MoveNext
Loop
' Clean up
'
objRecordSet.Close
Set objRecordSet = Nothing
Set objCommand = Nothing
objConnection.Close
Set objConnection = Nothing
Hi there,
This should get you enabled accounts only, compared to the master list, and put AD accounts that don't exist in the master list, into Results.txt.
Regards,
Rob.
This should get you enabled accounts only, compared to the master list, and put AD accounts that don't exist in the master list, into Results.txt.
Regards,
Rob.
strMasterList = "MasterList.txt"
strResults = "UsersNotInMasterList.txt"
arrOUs = Array( _
"OU=UserAccounts,OU=Office1,DC=domain,DC=com", _
"OU=UserAccounts,OU=Office2,DC=domain,DC=com" _
)
Set objFSO = CreateObject("Scripting.FileSystemObject")
Const ForReading = 1
Set objMaster = CreateObject("Scripting.Dictionary")
Set objMasterFile = objFSO.OpenTextFile(strMasterList, ForReading, False)
While Not objMasterFile.AtEndOfStream
strAccount = LCase(objMasterFile.ReadLine)
If objMaster.Exists(strAccount) = False Then objMaster.Add strAccount, 0
Wend
objMasterFile.Close
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
Set objResults = objFSO.CreateTextFile(strResults, True)
For Each strOU In arrOUs
objCommand.CommandText = "<LDAP://" & strOU & ">; (&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)));adsPath,samAccountName;Subtree"
Set objRecordSet = objCommand.Execute
Do Until objRecordSet.EOF
strSamAccountName = objRecordSet.Fields("samAccountName").Value
If objMaster.Exists(LCase(strSamAccountName)) = False Then objResults.WriteLine strSamAccountName
objRecordSet.MoveNext
Loop
Next
objResults.Close
MsgBox "Finished. Please see " & strResults
ASKER
Hi Rob,
Great to hear from you again, hope you are well. I ran your script above and for some reason it's erroring out on me:
************************** ********** ********** ********** ********** ********** ********** **********
Script: C:\Users\xxxxx\Desktop\Uni x-UserMapp ingToAD.vb s
Line: 30
Char: 2
Error: There is no such object on the server.
Code: 80040E37
Source: Active Directory
************************** ********** ********** ********** ********** ********** ********** **********
Again, thanks for chiming in on this.
Great to hear from you again, hope you are well. I ran your script above and for some reason it's erroring out on me:
**************************
Script: C:\Users\xxxxx\Desktop\Uni
Line: 30
Char: 2
Error: There is no such object on the server.
Code: 80040E37
Source: Active Directory
**************************
Again, thanks for chiming in on this.
Hi, you'll need to make sure these are correct:
"OU=UserAccounts,OU=Office 1,DC=domai n,DC=com"
remember that the OU's are specified backwards, so
domain.com\MySites\MainOff ice\Users
is referenced like this
"OU=Users,OU=MainOffice,OU =MySites,D C=Domain,D C=Com"
Regards,
Rob.
"OU=UserAccounts,OU=Office
remember that the OU's are specified backwards, so
domain.com\MySites\MainOff
is referenced like this
"OU=Users,OU=MainOffice,OU
Regards,
Rob.
ASKER
Hi Rob,
Double check the path and set those appropriately. However still getting the same error on line 30 w/character 2. I work in Notepad++, not sure if your using that or not.... What's interesting is I ran prashanthd code as well and got the same exact error.
Double check the path and set those appropriately. However still getting the same error on line 30 w/character 2. I work in Notepad++, not sure if your using that or not.... What's interesting is I ran prashanthd code as well and got the same exact error.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Try this
Dim NextTime As Date = Now ' Current date and time.
NextTime = NextTime.AddDays(1) ' Increment/Decrement
Please ignore above wrong post
ASKER
Hi Rob,
Your latest script provided did bring back a populated results file. The Master text file contains around 4000 sAMAccountNames, the file produced by the script generated around 49,000 sAMAccountNames. I'm thinking this has something to do with what you mentioned about changing the str path from OU=Users to CN=Users. Your correct, I will be only searching through 2 OU's in my Active Directory tree, not the entire tree. Can you tell me where I need to change OU= to CN= ? I think once we do this it will generate accurate numbers in comparison to the Master text file. Again, thank you so much for your help. You are appreciated!
I'm also going to try prashanthd code again, but remove the DC part to see if that helps too...
Your latest script provided did bring back a populated results file. The Master text file contains around 4000 sAMAccountNames, the file produced by the script generated around 49,000 sAMAccountNames. I'm thinking this has something to do with what you mentioned about changing the str path from OU=Users to CN=Users. Your correct, I will be only searching through 2 OU's in my Active Directory tree, not the entire tree. Can you tell me where I need to change OU= to CN= ? I think once we do this it will generate accurate numbers in comparison to the Master text file. Again, thank you so much for your help. You are appreciated!
I'm also going to try prashanthd code again, but remove the DC part to see if that helps too...
Hi, glad we got something.
I assume you only used
"CN=Users,"
in the array then?
Using CN= over OU= depends on how your user accounts are structured in their OUs, and ONLY applies to the default Users container.
For example, if you have the users separated like so:
domain.com/Users/Office1/U serAccount s
then you would use:
"OU=UserAccounts,OU=Office 1,CN=Users ,"
because the Users container from the root of the domain is the default one, and therefore is a CN, not an OU.
However, if your accounts were in a path that complete consisted of user created OUs, like:
domain.com/Office1/UserAcc ounts
then you would use:
"OU=UserAccounts,OU=Office 1,"
because they are all manually created organizational units.
Hope that helps.
Regards,
Rob.
I assume you only used
"CN=Users,"
in the array then?
Using CN= over OU= depends on how your user accounts are structured in their OUs, and ONLY applies to the default Users container.
For example, if you have the users separated like so:
domain.com/Users/Office1/U
then you would use:
"OU=UserAccounts,OU=Office
because the Users container from the root of the domain is the default one, and therefore is a CN, not an OU.
However, if your accounts were in a path that complete consisted of user created OUs, like:
domain.com/Office1/UserAcc
then you would use:
"OU=UserAccounts,OU=Office
because they are all manually created organizational units.
Hope that helps.
Regards,
Rob.
If you're still struggling with how to form the adsPath, then what you can do is place a test user account in the OU you need to know the path of, log in as that user, then run the following code:
You will then see an InputBox that has the OU text, exactly as you need to put it in the script.
Regards,
Rob.
Set objADSysInfo = CreateObject("ADSystemInfo")
Set objUser = GetObject("LDAP://" & objADSysInfo.UserName)
strOU = Left(Mid(objUser.Parent, 8), InStr(Mid(objUser.Parent, 8), ",DC="))
InputBox "Your account is in the following OU:", "OU Path", strOU
You will then see an InputBox that has the OU text, exactly as you need to put it in the script.
Regards,
Rob.
ASKER
Sounds like a plan. I'll run it tomorrow and let you know. : )
ASKER
Hi Rob, Yep I think everything is pathed in the OU format rather than the CN. I also run Active Directory Explorer on my end and drilled down to those two OU's I'm needing and in the path field at the top, it did NOT indicate anything i.e. CN=, it was all OU=,OU=,OU= so I think we are good to go with that.
What I did differently, because it was pulling so many more accounts than what was shown in the Master text file was included the other sub OU's under the primary OU in the array listing. That helped reduce the number of accounts it found for some reason. Unfortunately, because it's pulling all ACTIVE ACCOUNTs it's still pulling way more than what is listed in the Master text file. The other OU's look great it's the very last OU i.e. NORTHWEST that it's finding around 9,200 accounts. The Master text file only contains 4,900 or so accounts.
The OU structure the script is presently scanning is as such. All the hits look good until you get to the last OU where it is pulling 9200 accounts, which I assume are those it does not see in the Master text file as well as ALL Active Accounts in that OU. Perhaps we just need a way of telling the script, yes do pull ACTIVE ACCOUNTS but only pull those ACTIVE ACCOUNTS THAT it does not see in the Master Text file. I hope that makes sense.
Accts it does not see in Master Txt File
arrOUs = Array(
OU=NORTH,OU=ABC,OU=TEX,OU= UserAccoun ts,", _ 11
"OU=SOUTH,OU=ABC,OU=TEX,OU =UserAccou nts,", _ 2
"OU=EAST,OU=ABC,OU=TEX,OU= UserAccoun ts,", _ 81
"OU=WEST,OU=ABC,OU=TEX,OU= UserAccoun ts,", _ 70
"OU=SOUTHWEST,OU=ABC,OU=TE X,OU=UserA ccounts,", _ 0
"OU=NORTHEAST,OU=ABC,OU=TE X,OU=UserA ccounts,", _ 426
"OU=NORTHWEST,OU=ABC,OU=TE X,OU=UserA ccounts,", _ 7
"OU=SOUTHEAST,OU=ABC,OU=TE X,OU=UserA ccounts,", _ 53
"OU=NORTHEAST,OU=ABC,OU=TE X,OU=UserA ccounts," _ 9200
)
What I did differently, because it was pulling so many more accounts than what was shown in the Master text file was included the other sub OU's under the primary OU in the array listing. That helped reduce the number of accounts it found for some reason. Unfortunately, because it's pulling all ACTIVE ACCOUNTs it's still pulling way more than what is listed in the Master text file. The other OU's look great it's the very last OU i.e. NORTHWEST that it's finding around 9,200 accounts. The Master text file only contains 4,900 or so accounts.
The OU structure the script is presently scanning is as such. All the hits look good until you get to the last OU where it is pulling 9200 accounts, which I assume are those it does not see in the Master text file as well as ALL Active Accounts in that OU. Perhaps we just need a way of telling the script, yes do pull ACTIVE ACCOUNTS but only pull those ACTIVE ACCOUNTS THAT it does not see in the Master Text file. I hope that makes sense.
Accts it does not see in Master Txt File
arrOUs = Array(
OU=NORTH,OU=ABC,OU=TEX,OU=
"OU=SOUTH,OU=ABC,OU=TEX,OU
"OU=EAST,OU=ABC,OU=TEX,OU=
"OU=WEST,OU=ABC,OU=TEX,OU=
"OU=SOUTHWEST,OU=ABC,OU=TE
"OU=NORTHEAST,OU=ABC,OU=TE
"OU=NORTHWEST,OU=ABC,OU=TE
"OU=SOUTHEAST,OU=ABC,OU=TE
"OU=NORTHEAST,OU=ABC,OU=TE
)
I'm a bit confused as to why it's doing this. Here's what it should be doing:
1) Read the mast list accounts into the dictionary object called objMaster
2) Go through each OU in arrOUs
3) For each OU, get the list of ENABLED user accounts only
4) Check if each user is in the objMaster dictionary object
5) If it does exist, do nothing, if the account is NOT in the master list, output it to file
That's it. However, maybe you have further sub OUs in the NORTHEAST OU that you do not want to check? If that's the case, then change:
strCommandText = "<LDAP://" & strOU & strDomain & ">; (&(objectCategory=person)( objectClas s=user)(!( userAccoun tControl:1 .2.840.113 556.1.4.80 3:=2)));ad sPath,samA ccountName ;Subtree"
to:
strCommandText = "<LDAP://" & strOU & strDomain & ">; (&(objectCategory=person)( objectClas s=user)(!( userAccoun tControl:1 .2.840.113 556.1.4.80 3:=2)));ad sPath,samA ccountName ;OneLevel"
Regards,
Rob.
1) Read the mast list accounts into the dictionary object called objMaster
2) Go through each OU in arrOUs
3) For each OU, get the list of ENABLED user accounts only
4) Check if each user is in the objMaster dictionary object
5) If it does exist, do nothing, if the account is NOT in the master list, output it to file
That's it. However, maybe you have further sub OUs in the NORTHEAST OU that you do not want to check? If that's the case, then change:
strCommandText = "<LDAP://" & strOU & strDomain & ">; (&(objectCategory=person)(
to:
strCommandText = "<LDAP://" & strOU & strDomain & ">; (&(objectCategory=person)(
Regards,
Rob.
ASKER
Will do, I'll check that and let you know Rob. Thank you again!
Hi, did you manage to get back to try this out?
Rob.
Rob.
ASKER
Thanks! Great input!
No problem. Thanks for the grade.
Rob.
Rob.
Open in new window