Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

LDAP Query 1

Status
Not open for further replies.

gmagerr

Technical User
Aug 11, 2001
323
US
I found a script online and I'm trying to modify it to omit the Servers OU in AD. I've tried strFilter = "(&(objectCategory=computer)(!OU=Servers))" also !CN=Servers nothing is working. I'm getting a very large list of computers but some of them are in sub OU's of the servers OU. I just want everything in the Computers container. Can someone help?

Thanks

Code:
' MoveOldComputers.vbs
' VBScript program to determine when each computer account in the domain
' last had their password changed. If this date is more than a specified
' number of days in the past, the computer object is considered inactive
' and it is moved to a target Organizational Unit. The computer account
' is also disabled. A log file keeps track of which computer objects are
' moved.
'
' ----------------------------------------------------------------------
' Copyright (c) 2004 Richard L. Mueller
' Hilltop Lab web site - [URL unfurl="true"]http://www.rlmueller.net[/URL]
' Version 1.0 - February 8, 2004
' Version 1.1 - February 23, 2004 - Bug fix.
' Version 1.2 - July 6, 2007 - Modify how IADsLargeInteger interface
'                              is invoked.
' Version 1.3 - July 31, 2007 - Escape any "/" characters in computer
'                               DNs.
'
' You have a royalty-free right to use, modify, reproduce, and
' distribute this script file in any way you find useful, provided that
' you agree that the copyright owner above has no warranty, obligations,
' or liability for such use.

Option Explicit

Dim strFilePath, objFSO, objFile, adoConnection, adoCommand
Dim objRootDSE, strDNSDomain, strFilter, strQuery, adoRecordset
Dim strComputerDN, objShell, lngBiasKey, lngBias
Dim objDate, dtmPwdLastSet, k
Dim intDays, strTargetOU, objTargetOU, objComputer
Dim intTotal, intInactive, intNotMoved, intNotDisabled

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("Wscript.Shell")
objFSO.CreateTextFile("c:\OldComputers.txt")


' Specify the log file. This file will be created if it does not
' exist. Otherwise, the program will append to the file.

strFilePath = "c:\OldComputers.txt"

' Specify the minimum number of days since the password was last set for
' the computer account to be considered inactive.
intDays = 365

' Specify the Distinguished Name of the Organizational Unit into
' which inactive computer objects will be moved.
strTargetOU = "ou=Disabled_Computers"

' Bind to target Organizational Unit.
On Error Resume Next
Set objTargetOU = GetObject("LDAP://" & strTargetOU)
If (Err.Number <> 0) Then
    On Error GoTo 0
    Wscript.Echo "Organization Unit not found: " & strTargetOU
    Wscript.Quit
End If
On Error GoTo 0

' Open the log file for write access. Append to this file.
On Error Resume Next
Set objFile = objFSO.OpenTextFile(strFilePath, 8, True, 0)
If (Err.Number <> 0) Then
    On Error GoTo 0
    Wscript.Echo "File " & strFilePath & " cannot be opened"
    Set objFSO = Nothing
    Wscript.Quit
End If
On Error GoTo 0

' Obtain local time zone bias from machine registry.
lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" _
    & "TimeZoneInformation\ActiveTimeBias")
If (UCase(TypeName(lngBiasKey)) = "LONG") Then
    lngBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
    lngBias = 0
    For k = 0 To UBound(lngBiasKey)
        lngBias = lngBias + (lngBiasKey(k) * 256^k)
    Next
End If

' Use ADO to search the domain for all computers.
Set adoConnection = CreateObject("ADODB.Connection")
Set adoCommand = CreateObject("ADODB.Command")
adoConnection.Provider = "ADsDSOOBject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection

' Determine the DNS domain from the RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")

' Filter to retrieve all computer objects.
strFilter = "(objectCategory=computer)"


' Retrieve Distinguished Name and date password last set.
strQuery = "<LDAP://" & strDNSDomain & ">;" & strFilter & ";distinguishedName,pwdLastSet;subtree"

adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Write information to log file.
objFile.WriteLine "Search for Inactive Computer Accounts"
objFile.WriteLine "Start: " & Now
objFile.WriteLine "Base of search: " & strDNSDomain
objFile.WriteLine "Log File: " & strFilePath
objFile.WriteLine "Inactive if password not set in days: " & intDays
objFile.WriteLine "Inactive accounts moved to: " & strTargetOU
objFile.WriteLine "----------------------------------------------"

' Initialize totals.
intTotal = 0
intInactive = 0
intNotMoved = 0
intNotDisabled = 0

' Enumerate all computers and determine which are inactive.
Set adoRecordset = adoCommand.Execute
Do Until adoRecordset.EOF
    strComputerDN = adoRecordset.Fields("distinguishedName").Value
    ' Escape any forward slash characters, "/", with the backslash
    ' escape character. All other characters that should be escaped are.
    strComputerDN = Replace(strComputerDN, "/", "\/")
    intTotal = intTotal + 1
    ' Determine date when password last set.
    Set objDate = adoRecordset.Fields("pwdLastSet").Value
    dtmPwdLastSet = Integer8Date(objDate, lngBias)
    ' Check if computer object inactive.
    If (DateDiff("d", dtmPwdLastSet, Now) > intDays) Then
        ' Computer object inactive.
        intInactive = intInactive + 1
        objFile.WriteLine "Inactive: " & strComputerDN & " - password last set: " & dtmPwdLastSet
        ' Move computer object to the target OU.
'        On Error Resume Next
'        Set objComputer = objTargetOU.MoveHere("LDAP://" & strComputerDN, vbNullString)
'        If (Err.Number <> 0) Then
'            On Error GoTo 0
'            intNotMoved = intNotMoved + 1
'            objFile.WriteLine "Cannot move: " & strComputerDN
'        End If
        ' Disable the computer account.
'        On Error Resume Next
'        objComputer.AccountDisabled = True
        ' Save changes to Active Directory.
'        objComputer.SetInfo
'        If (Err.Number <> 0) Then
'            On Error GoTo 0
'            intNotDisabled = intNotDisabled + 1
'            objFile.WriteLine "Cannot disable: " & strComputerDN
'        End If
'        On Error GoTo 0
    End If
    adoRecordset.MoveNext
Loop
adoRecordset.Close

' Write totals to log file.
objFile.WriteLine "Finished: " & Now
objFile.WriteLine "Total computer objects found:   " & intTotal
objFile.WriteLine "Inactive:                       " & intInactive
objFile.WriteLine "Inactive accounts not moved:    " & intNotMoved
objFile.WriteLine "Inactive accounts not disabled: " & intNotDisabled
objFile.WriteLine "----------------------------------------------"

' Display summary.
'Wscript.Echo "Computer objects found:         " & intTotal
'Wscript.Echo "Inactive:                       " & intInactive
'Wscript.Echo "Inactive accounts not moved:    " & intNotMoved
'Wscript.Echo "Inactive accounts not disabled: " & intNotDisabled
'Wscript.Echo "See log file: " & strFilePath

' Clean up.
objFile.Close
adoConnection.Close
Set objFile = Nothing
Set objFSO = Nothing
Set objShell = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing
Set objRootDSE = Nothing
Set adoRecordset = Nothing
Set objComputer = Nothing

Wscript.Echo "Done"

Function Integer8Date(objDate, lngBias)
    ' Function to convert Integer8 (64-bit) value to a date, adjusted for
    ' time zone bias.
    Dim lngAdjust, lngDate, lngHigh, lngLow
    lngAdjust = lngBias
    lngHigh = objDate.HighPart
    lngLow = objDate.LowPart
    ' Account for bug in IADsLargeInteger property methods.
    If (lngHigh = 0) And (lngLow = 0) Then
        lngAdjust = 0
    End If
    lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) + lngLow) / 600000000 - lngAdjust) / 1440
    Integer8Date = CDate(lngDate)
End Function
 
I doubt you have so many servers that you need to worry about performance issues witht he query, so give this a try to filter those entries out. See the text in [red]RED[/red].
Code:
strComputerDN = adoRecordset.Fields("distinguishedName").Value

[red]If Instr(strComputerDN,"OU=Servers") = 0 Then[/red]
  ' Escape any forward slash characters, "/", with the backslash
    ' escape character. All other characters that should be escaped are.
    strComputerDN = Replace(strComputerDN, "/", "\/")
    intTotal = intTotal + 1
    ' Determine date when password last set.
    Set objDate = adoRecordset.Fields("pwdLastSet").Value
    dtmPwdLastSet = Integer8Date(objDate, lngBias)
    ' Check if computer object inactive.
    If (DateDiff("d", dtmPwdLastSet, Now) > intDays) Then
        ' Computer object inactive.
        intInactive = intInactive + 1
        objFile.WriteLine "Inactive: " & strComputerDN & " - password last set: " & dtmPwdLastSet
        ' Move computer object to the target OU.
'        On Error Resume Next
'        Set objComputer = objTargetOU.MoveHere("LDAP://" & strComputerDN, vbNullString)
'        If (Err.Number <> 0) Then
'            On Error GoTo 0
'            intNotMoved = intNotMoved + 1
'            objFile.WriteLine "Cannot move: " & strComputerDN
'        End If
        ' Disable the computer account.
'        On Error Resume Next
'        objComputer.AccountDisabled = True
        ' Save changes to Active Directory.
'        objComputer.SetInfo
'        If (Err.Number <> 0) Then
'            On Error GoTo 0
'            intNotDisabled = intNotDisabled + 1
'            objFile.WriteLine "Cannot disable: " & strComputerDN
'        End If
'        On Error GoTo 0
    End If
[red]End If[/red]
    adoRecordset.MoveNext


I hope you find this post helpful.  

Regards,

Mark

Check out my scripting solutions at [URL unfurl="true"]http://www.thespidersparlor.com/vbscript[/URL]

Work SMARTER not HARDER.  The Spider's Parlor's Admin Script Pack is a collection of Administrative scripts designed to make IT Administration easier!  Save time, get more work done, get the Admin Script Pack.
 
Mark

You're so good at this sometimes it scary.

Thanks.
 
Thanks, sometimes the simpler solution is the best. Not always, but sometimes.

I hope you find this post helpful.

Regards,

Mark

Check out my scripting solutions at
Work SMARTER not HARDER. The Spider's Parlor's Admin Script Pack is a collection of Administrative scripts designed to make IT Administration easier! Save time, get more work done, get the Admin Script Pack.
 
Mark
Is there a way to filter out other OU's here?

If Instr(strComputerDN,"OU=Servers") = 0 Then

Thanks.
 
Code:
If Instr(strComputerDN,"OU=Servers") = 0 And Instr(strComputerDN,"OU=DomainControllers") = 0 Then

Or if you have multiple criteria then an array to hold the OUs may be more robust for you. Here is a trimmed down example:

Code:
strComputerDN = "Ipsem lorem OU=Servers"


Dim CheckArray(2)
CheckArray(0) = "OU=Servers"
CheckArray(1) = "OU=DomainControllers"
CheckArray(2) = "OU=TerminalServers"


IgnoreFlag = "No"

For Each OU In CheckArray
	If InStr(strComputerDN, OU) <> 0 Then
		IgnoreFlag = "Yes"
	End If
Next
If IgnoreFlag = "Yes" Then
	WScript.Echo "Ignore this OU"
Else
	WScript.Echo "Process this OU"
End If
IgnoreFlag = "No"

I hope you find this post helpful.

Regards,

Mark

Check out my scripting solutions at
Work SMARTER not HARDER. The Spider's Parlor's Admin Script Pack is a collection of Administrative scripts designed to make IT Administration easier! Save time, get more work done, get the Admin Script Pack.
 
Fantastic!!
I was thinking about the array, but wasn't sure. Thanks again Mark.
 
What is the strComputerDN = "Ipsem lorem OU=Servers"
would I put strComputer = CheckArray instead? I didn't understand the Ipsem lorem
 
That was just a placeholder. It is bogus text that I used to test the array code with. The strComputerDN comes from your code and would be something like:
cn=computers,ou=sales,dc=company,dc.com

The array is just looking for ou=servers etc, no matter where int he string it exists.

Clear now?

I hope you find this post helpful.

Regards,

Mark

Check out my scripting solutions at
Work SMARTER not HARDER. The Spider's Parlor's Admin Script Pack is a collection of Administrative scripts designed to make IT Administration easier! Save time, get more work done, get the Admin Script Pack.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top