Cleanup AD using vbs

Hi,
I'm working to do an automated process that will move computers from a specific OU to another based on a set of rules.
The rules state that if a Computer is named XXX and the type of the OS is Windows XP then Move to ZZZ OU.
Thus creating a predetermined set of rules and run a schedule task.
Can it be done?
johnnyjonathanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

bluntTonyHead of ICTCommented:
The below vbs checks for the existence of a string in the computer name, then checks for the existence of a string in the Operating System. If both are found, then the computer is moved to the new OU.
Just change strOS, strSearch, and objOU to suit your needs (lines 9, 10 and 11)
You can schedule this vbs to run as a scheduled task if you wish. It currently has no feedback so runs silently.
Hope this helps...

Set oRootDSE = GetObject("LDAP://RootDSE")
Set objConn = CreateObject("ADODB.Connection")
Set objComm =   CreateObject("ADODB.Command")
objConn.Provider = "ADsDSOObject"
objConn.Open "Active Directory Provider"
Set objComm.ActiveConnection = objConn
objComm.Properties("Page Size") = 1000
 
strSearch = "XXXX" ' The string to search for in the computer name
strOS = "XP" ' The string to search for in Operating System
Set objOU = GetObject("LDAP://OU=someOU,DC=domain,DC=local") ' The OU to move the objects to
 
strBase   =  "<LDAP://" & oRootDSE.get("defaultNamingContext") & ">;"
strFilter = "(&(objectclass=computer)(cn=*" & strSearch & "*)(operatingSystem=*" & strOS & "*));" 
strAttrs  = "distinguishedName;"
strScope  = "subtree"
 
objComm.CommandText = strBase & strFilter & strAttrs & strScope
Set objRS = objComm.Execute
 
If objRS.RecordCount > 0 Then
	objRS.MoveFirst
	Do Until objRS.EOF
		Set objComp = GetObject("LDAP://" & Replace(objRS.Fields(0).Value,"/","\/"))
		objOU.MoveHere objComp.distinguishedName, objComp.name
		objRS.MoveNext
	Loop
End If
 
Set oRootDSE = Nothing
Set objConn = Nothing
Set objComm = Nothing
Set objOU = Nothing
Set objRS = Nothing
Set objComp = Nothing

Open in new window

0
johnnyjonathanAuthor Commented:
hi bluntTony, is there anyway i can also exclude specific computers from this filter with that script? it seemed to remove default machines in the ou that wern't suppose to be moved
0
bluntTonyHead of ICTCommented:
You can add these machine names to a text file. Any machines listed in this file will be excluded from processing in the following script.

You now also have strFile to designate the path to the text file.
Set oRootDSE = GetObject("LDAP://RootDSE")
Set objConn = CreateObject("ADODB.Connection")
Set objComm =   CreateObject("ADODB.Command")
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objDict = CreateObject("Scripting.Dictionary")
 
Const ForReading = 1
 
objConn.Provider = "ADsDSOObject"
objConn.Open "Active Directory Provider"
Set objComm.ActiveConnection = objConn
objComm.Properties("Page Size") = 1000
 
strSearch = "XXXX" ' The string to search for in the computer name
strOS = "XP" ' The string to search for in Operating System
strFile = "c:\test.txt"
Set objOU = GetObject("LDAP://OU=someOU,DC=domain,DC=local") ' The OU to move the objects to
 
Set objTxt = objFso.OpenTextFile(strFile,ForReading)
 
While Not objTxt.AtEndOfStream
	strLine = UCase(objTxt.ReadLine)
	objDict.Add strLine, strLine
Wend
 
strBase   =  "<LDAP://" & oRootDSE.get("defaultNamingContext") & ">;"
strFilter = "(&(objectclass=computer)(cn=*" & strSearch & "*)(operatingSystem=*" & strOS & "*));" 
strAttrs  = "distinguishedName;"
strScope  = "subtree"
 
objComm.CommandText = strBase & strFilter & strAttrs & strScope
Set objRS = objComm.Execute
 
If objRS.RecordCount > 0 Then
        objRS.MoveFirst
        Do Until objRS.EOF
                Set objComp = GetObject("LDAP://" & Replace(objRS.Fields(0).Value,"/","\/"))
                If Not objDict.Exists(UCase(objComp.cn)) Then
                	objOU.MoveHere objComp.distinguishedName, objComp.name
	                objRS.MoveNext	
                End If
        Loop
End If
 
Set oRootDSE = Nothing
Set objConn = Nothing
Set objComm = Nothing
Set objOU = Nothing
Set objRS = Nothing
Set objComp = Nothing
Set objFso = Nothing
Set objTxt = Nothing

Open in new window

0
Big Business Goals? Which KPIs Will Help You

The most successful MSPs rely on metrics – known as key performance indicators (KPIs) – for making informed decisions that help their businesses thrive, rather than just survive. This eBook provides an overview of the most important KPIs used by top MSPs.

johnnyjonathanAuthor Commented:
thank you Tony, i see the OU to move the objects to but where is the original OU where it takes the computer names from?

is it LDAP://" & oRootDSE?
0
bluntTonyHead of ICTCommented:
Yes, at the moment, the base of the search is the top of the domain and the scope is 'subtree' which basically means look everywhere in your current domain.

If you want to narrow the search, change line 26 to to DN of the OU you want to look in e.g:

strBase   =  ";"

If you want to search all OUs beneath this one, leave line 29 as it is. If you want to search in just that OU, change line 29 to:

strScope  = "onelevel"

Hope this helps!

0
johnnyjonathanAuthor Commented:
hi,
i get:

(39, 25) Active Directory: An invalid directory pathname was passed
0
bluntTonyHead of ICTCommented:
hmmm. Looks like a small error in my code. Try this:
Set oRootDSE = GetObject("LDAP://RootDSE")
Set objConn = CreateObject("ADODB.Connection")
Set objComm =   CreateObject("ADODB.Command")
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objDict = CreateObject("Scripting.Dictionary")
 
Const ForReading = 1
 
objConn.Provider = "ADsDSOObject"
objConn.Open "Active Directory Provider"
Set objComm.ActiveConnection = objConn
objComm.Properties("Page Size") = 1000
 
strSearch = "XXXX" ' The string to search for in the computer name
strOS = "XP" ' The string to search for in Operating System
strFile = "c:\test.txt"
Set objOU = GetObject("LDAP://OU=someOU,DC=domain,DC=local") ' The OU to move the objects to
 
Set objTxt = objFso.OpenTextFile(strFile,ForReading)
 
While Not objTxt.AtEndOfStream
        strLine = UCase(objTxt.ReadLine)
        objDict.Add strLine, strLine
Wend
 
strBase   =  "<LDAP://" & oRootDSE.get("defaultNamingContext") & ">;"
strFilter = "(&(objectclass=computer)(cn=*" & strSearch & "*)(operatingSystem=*" & strOS & "*));" 
strAttrs  = "distinguishedName;"
strScope  = "subtree"
 
objComm.CommandText = strBase & strFilter & strAttrs & strScope
Set objRS = objComm.Execute
 
If objRS.RecordCount > 0 Then
        objRS.MoveFirst
        Do Until objRS.EOF
                Set objComp = GetObject("LDAP://" & Replace(objRS.Fields(0).Value,"/","\/"))
                If Not objDict.Exists(UCase(objComp.cn)) Then
                        objOU.MoveHere objComp.distinguishedName, objComp.name  
                End If
                objRS.MoveNext
        Loop
End If
 
Set oRootDSE = Nothing
Set objConn = Nothing
Set objComm = Nothing
Set objOU = Nothing
Set objRS = Nothing
Set objComp = Nothing
Set objFso = Nothing
Set objTxt = Nothing

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
johnnyjonathanAuthor Commented:
hi,
thanks for the changges but i still get:

(32, 1) Active Directory: An invalid directory pathname was passed

the only thing i'm changing is line 26
strBase   =  "<LDAP://" & oRootDSE.get("defaultNamingContext") & ">;"

to
strBase   =  "<LDAP://OU=someOU,DC=domain,DC=local & oRootDSE.get("defaultNamingContext") & ">;"

of course with my OU's details.
same goes to line 17
0
bluntTonyHead of ICTCommented:
Sorry for the delay in replying. You need to remove the oRootDSE object completely. So line 26 should look like:
strBase   =  "<LDAP://OU=someOU,DC=domain,DC=local>;"
This will mean that the search will start at this OU downwards.
0
johnnyjonathanAuthor Commented:
Hi Tony, no problem, i've done as you requested but now i get this error -

(39, 25) Active Directory: An invalid directory pathname was passed
but only sometimes, in other times, it works but i can't see any computers moving from an OU to OU?
 
 
0
johnnyjonathanAuthor Commented:

I found a question that looks like mine with a solution running, however without a search for a naming based context -

http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_24102299.html?sfQueryTermInfo=1+creat+ou

can we modify it to fit my requirements?  
0
Chris DentPowerShell DeveloperCommented:

> objOU.MoveHere objComp.distinguishedName

This line should be:

objOU.MoveHere objComp.ADSPath, vbNullString

Or:

objOU.MoveHere "LDAP://" & objComp.distinguishedName, vbNullString

Chris
0
bluntTonyHead of ICTCommented:
Apologies - this one seemed to have slipped though my inbox.

Thanks for the catch, Chris.
0
johnnyjonathanAuthor Commented:
Works perfect!
thank you!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
VB Script

From novice to tech pro — start learning today.