Re: HELP! Need AD Query for Last login
- From: "LOST" <LOST@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Mon, 4 Jul 2005 10:56:09 -0700
Thanks a million it worked like a charm.....
It took about 45 mins to check all 6100 users in my OU. I can only think
that it would take all day if it checked the entire domain of 100,000
users....... Thanks again for the great tips that you provided.
"Richard Mueller [MVP]" wrote:
> Hi,
>
> To restrict the query to one domain, you need to modify the "base" of the
> search. You want to do this only for the second query that runs on each DC.
> As written, the variable strBase is defined by the statement:
>
> strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
>
> where strDNSDomain is the DNS name of the domain (retrieved from the rootDSE
> object). For your purpose, redefine strDNSDomain to be the Distinguished
> Name of the specific OU. For example:
>
> strDNSDomain = "ou=Sales,ou=West,dc=MyDomain,dc=com"
>
> Unfortunately, you still must query all DC's, as users could have logged in
> from anywhere and been authenticated by any DC. Finally, if your domain is
> at Windows 2003 functional level, you can query a single DC for the new
> attribute lastLogonTimeStamp. This attribute is replicated, although it is
> only updated if at least a week has passed since the last update.
>
> If the original script ran to completion, I'd like to know how long it took,
> and how long the revised script (restricting the query to one OU) took. From
> experience, performance depends on the number of remote sites and the speed
> of the links. Even though the number of users may be much less, the revised
> script may not be much faster. Still, some people have been very happy that
> the program finished in an hour, as they had no better alternative.
>
> --
> Richard
> Microsoft MVP Scripting and ADSI
> Hilltop Lab web site - http://www.rlmueller.net
> --
>
> "LOST" <LOST@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
> news:760761F5-701B-45BC-9EF4-847D75B7C223@xxxxxxxxxxxxxxxx
> > Hi all:
> >
> > I am stuck: I need to query a specific OU in a large AD Structure (over
> > 100K user hence why a specifc OU) I need to determine and then export to a
> > text or excel file all of the users in the OU that have a last login in
> date
> > more then 30 days. Now I have read that the last login is not replicated
> to
> > all DCs and that one will have to check all DCs for the last login date. I
> > found a script listed below that will automaticly query the domain and
> find
> > all of the DCs and then list all of the users that have not logged in for
> a
> > long time, but it will only run on the entire domain hence it has to check
> > all 100K user on each DC and then compare them and it takes for ever! Can
> > anyone par it down so that it still querys the Domain for all of the DCs
> and
> > then determine the last login date over 30 days for a certian OU? Thanks
> >
> >
> > ' Copyright (c) 2002 Richard L. Mueller royalty-free right to use
> > ' Hilltop Lab web site - http://www.rlmueller.net
> > ' Version 1.0 - December 7, 2002
> > ' Version 1.1 - January 17, 2003 - Account for null value for lastLogon.
> > ' Version 1.2 - January 23, 2003 - Account for DC not available.
> > ' Version 1.3 - February 3, 2003 - Retrieve users but not contacts.
> > ' Version 1.4 - February 19, 2003 - Standardize Hungarian notation.
> > ' Version 1.5 - March 11, 2003 - Remove SearchScope property.
> > ' Version 1.6 - May 9, 2003 - Account for error in IADsLargeInteger
> > ' property methods HighPart and LowPart.
> > ' Version 1.7 - January 25, 2004 - Modify error trapping.
> > '
> > ' Because the lastLogon attribute is not replicated, every Domain
> > ' Controller in the domain must be queried to find the latest lastLogon
> > ' date for each user. The lastest date found is kept in a dictionary
> > ' object. The program first uses ADO to search the domain for all Domain
> > ' Controllers. The AdsPath of each Domain Controller is saved in an
> > ' array. Then, for each Domain Controller, ADO is used to search the
> > ' copy of Active Directory on that Domain Controller for all user
> > ' objects and return the lastLogon attribute. The lastLogon attribute is
> > ' a 64-bit number representing the number of 100 nanosecond intervals
> > ' since 12:00 am January 1, 1601. This value is converted to a date. The
> > ' last logon date is in UTC (Coordinated Univeral Time). It must be
> > ' adjusted by the Time Zone bias in the machine registry to convert to
> > ' local time.
> > '
> > ' 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 objRootDSE, strConfig, objConnection, objCommand, strQuery
> > Dim objRecordSet, objDC
> > Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
> > Dim strDN, dtmDate, objDate, lngDate, objList, strUser
> > Dim strBase, strFilter, strAttributes, lngHigh, lngLow
> >
> > ' Use a dictionary object to track latest lastLogon for each user.
> > Set objList = CreateObject("Scripting.Dictionary")
> > objList.CompareMode = vbTextCompare
> >
> > ' Obtain local Time Zone bias from machine registry.
> > Set objShell = CreateObject("Wscript.Shell")
> > 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
> >
> > ' Determine configuration context and DNS domain from RootDSE object.
> > Set objRootDSE = GetObject("LDAP://RootDSE")
> > strConfig = objRootDSE.Get("configurationNamingContext")
> > strDNSDomain = objRootDSE.Get("defaultNamingContext")
> >
> > ' Use ADO to search Active Directory for ObjectClass nTDSDSA.
> > ' This will identify all Domain Controllers.
> > Set objCommand = CreateObject("ADODB.Command")
> > Set objConnection = CreateObject("ADODB.Connection")
> > objConnection.Provider = "ADsDSOObject"
> > objConnection.Open "Active Directory Provider"
> > objCommand.ActiveConnection = objConnection
> >
> > strBase = "<LDAP://" & strConfig & ">"
> > strFilter = "(objectClass=nTDSDSA)"
> > strAttributes = "AdsPath"
> > strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
> >
> > objCommand.CommandText = strQuery
> > objCommand.Properties("Page Size") = 100
> > objCommand.Properties("Timeout") = 60
> > objCommand.Properties("Cache Results") = False
> >
> > Set objRecordSet = objCommand.Execute
> >
> > ' Enumerate parent objects of class nTDSDSA. Save Domain Controller
> > ' AdsPaths in dynamic array arrstrDCs.
> > k = 0
> > Do Until objRecordSet.EOF
> > Set objDC = _
> > GetObject(GetObject(objRecordSet.Fields("AdsPath")).Parent)
> > ReDim Preserve arrstrDCs(k)
> > arrstrDCs(k) = objDC.DNSHostName
> > k = k + 1
> > objRecordSet.MoveNext
> > Loop
> >
> > ' Retrieve lastLogon attribute for each user on each Domain Controller.
> > For k = 0 To Ubound(arrstrDCs)
> > strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
> > strFilter = "(&(objectCategory=person)(objectClass=user))"
> > strAttributes = "distinguishedName,lastLogon"
> > strQuery = strBase & ";" & strFilter & ";" & strAttributes _
> > & ";subtree"
> > objCommand.CommandText = strQuery
> > On Error Resume Next
> > Set objRecordSet = objCommand.Execute
> > If Err.Number <> 0 Then
> > On Error GoTo 0
> > Wscript.Echo "Domain Controller not available: " & arrstrDCs(k)
> > Else
> > On Error GoTo 0
> > Do Until objRecordSet.EOF
> > strDN = objRecordSet.Fields("distinguishedName")
> > lngDate = objRecordSet.Fields("lastLogon")
> > On Error Resume Next
> > Set objDate = lngDate
> > If Err.Number <> 0 Then
> > On Error GoTo 0
> > dtmDate = #1/1/1601#
> > Else
> > On Error GoTo 0
> > lngHigh = objDate.HighPart
> > lngLow = objDate.LowPart
> > If lngLow < 0 Then
> > lngHigh = lngHigh + 1
> > End If
> > If (lngHigh = 0) And (lngLow = 0 ) Then
> > dtmDate = #1/1/1601#
> > Else
> > dtmDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
> > + lngLow)/600000000 - lngBias)/1440
> > End If
> > End If
> > If objList.Exists(strDN) Then
> > If dtmDate > objList(strDN) Then
> > objList(strDN) = dtmDate
> > End If
> > Else
> > objList.Add strDN, dtmDate
> > End If
> > objRecordSet.MoveNext
> > Loop
> > End If
> > Next
> >
> > ' Output latest lastLogon date for each user.
> > For Each strUser In objList
> > Wscript.Echo strUser & " ; " & objList(strUser)
> > Next
> >
> > ' Clean up.
> > objConnection.Close
> > Set objRootDSE = Nothing
> > Set objConnection = Nothing
> > Set objCommand = Nothing
> > Set objRecordSet = Nothing
> > Set objDC = Nothing
> > Set objDate = Nothing
> > Set objList = Nothing
> > Set objShell = Nothing
> >
>
>
>
.
- References:
- HELP! Need AD Query for Last login
- From: LOST
- Re: HELP! Need AD Query for Last login
- From: Richard Mueller [MVP]
- HELP! Need AD Query for Last login
- Prev by Date: Recurse issue - 2nd try
- Next by Date: Re: Parsing binary values in the registry
- Previous by thread: Re: HELP! Need AD Query for Last login
- Next by thread: Re: HELP! Need AD Query for Last login
- Index(es):
Relevant Pages
|