This is a simple VBScript that will enumerate all user accounts in a domain and their LastLogon date.
Because the LastLogon attribute is not replicated among domain controllers, this will need to be run against each DC in your domain for accurate results. In the case of a single DC, this works like a charm.
- Credit: Tektonic from this post on the Kaseya forum
- Download both files in a ZIP
adLastLogin.vbs
Usage: cscript lastlogon.vbs >
Option Explicit
Dim objRootDSE, strConfig, adoConnection, adoCommand, strQuery
Dim adoRecordset, objDC
Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
Dim strDN, dtmDate, objDate, 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 adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection
strBase = ""
strFilter = "(objectClass=nTDSDSA)"
strAttributes = "AdsPath"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 60
adoCommand.Properties("Cache Results") = False
Set adoRecordset = adoCommand.Execute
' Enumerate parent objects of class nTDSDSA. Save Domain Controller
' AdsPaths in dynamic array arrstrDCs.
k = 0
Do Until adoRecordset.EOF
Set objDC = _
GetObject(GetObject(adoRecordset.Fields("AdsPath").Value).Parent)
ReDim Preserve arrstrDCs(k)
arrstrDCs(k) = objDC.DNSHostName
k = k + 1
adoRecordset.MoveNext
Loop
adoRecordset.Close
' Retrieve lastLogon attribute for each user on each Domain Controller.
For k = 0 To Ubound(arrstrDCs)
strBase = ""
strFilter = "(&(objectCategory=person)(objectClass=user))"
strAttributes = "distinguishedName,lastLogon"
strQuery = strBase & ";" & strFilter & ";" & strAttributes _
& ";subtree"
adoCommand.CommandText = strQuery
On Error Resume Next
Set adoRecordset = adoCommand.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 adoRecordset.EOF
strDN = adoRecordset.Fields("distinguishedName").Value
On Error Resume Next
Set objDate = adoRecordset.Fields("lastLogon").Value
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) = True) Then
If (dtmDate > objList(strDN)) Then
objList.Item(strDN) = dtmDate
End If
Else
objList.Add strDN, dtmDate
End If
adoRecordset.MoveNext
Loop
adoRecordset.Close
End If
Next
' Output latest lastLogon date for each user.
For Each strUser In objList.Keys
Wscript.Echo strUser & " ; " & objList.Item(strUser)
Next
' Clean up.
adoConnection.Close
Set objRootDSE = Nothing
Set adoConnection = Nothing
Set adoCommand = Nothing
Set adoRecordset = Nothing
Set objDC = Nothing
Set objDate = Nothing
Set objList = Nothing
Set objShell = Nothing
Kaseya Script
Script Name: Dump LastLogon Attribute to E-Mail
Script Description: PLEASE NOTE: The attribute "LastLogon" is not replicated between Domain Controllers. This means that in a multi-site AD configuration, you will need to run this against all DCs in order to get appropriate results. Check the DC responsible for each site respectively.
IF True
THEN
Get Variable
Parameter 1 : 10
Parameter 2 :
Parameter 3 : AgentTmp
OS Type : 0
Get Variable
Parameter 1 : 6
Parameter 2 :
Parameter 3 : MachineID
OS Type : 0
Write File
Parameter 1 : #AgentTmp#\LastLogon.vbs
Parameter 2 : VSASharedFiles\LastLogon.vbs
OS Type : 0
Write Script Log Entry
Parameter 1 : Start: Dumping LastLogon entries...
OS Type : 0
Use Credential
OS Type : 0
Execute Shell Command
Parameter 1 : cscript "#AgentTmp#\LastLogon.vbs" >> "#AgentTmp#\LastLogon.txt"
Parameter 2 : 0
OS Type : 0
Write Script Log Entry
Parameter 1 : Done: LastLogon Attributes dumped to #AgentTmp#\LastLogon.txt
OS Type : 0
Get Variable
Parameter 1 : 1
Parameter 2 : #AgentTmp#\LastLogon.txt
Parameter 3 : LastLogon
OS Type : 0
Send Email
Parameter 1 : This email address is being protected from spambots. You need JavaScript enabled to view it.
Parameter 2 : LastLogon Report on all AD users on #MachineID#
Parameter 3 : #LastLogon#
OS Type : 0
Write Script Log Entry
Parameter 1 : Complete: Script "Dump LastLogon Attributes to E-Mail" completed
OS Type : 0
ELSE
