在许多IT企业由于管理不善,AD用户账号出现大量过期或不在使用中的账户,如何有效导出这些用户账户最后一次登录时间,经过IT部确认之后再删除这些用户,而不是直接删除XX天前未登录的用户(比如有些账户不一定需要登录,但却非常重要,比如一些邮箱账户或资源账户),微软提供了CSDEV工具,这个工具可以导出用户属性的Lastlogon,但是导出的结果有一个问题,是一串的数字,需要经过多次转换才能变成相应的日期和时间(转换方法可以参考:http://www.mcse.org.cn/showtopic-6953.html),有没有更好的办法,当然有,而且还不少,比较利用工具truelastlogon,reallastlogon,oldcmp,除此之外还有更好的方法就是VBS脚本,下面以一个叫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.
' This bias changes with Daylight Savings Time.
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 = "<LDAP://" & strConfig & ">"
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 = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
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
If (objList.Item(strUser) = #1/1/1601#) Then
Wscript.Echo strUser & ";Never"
Else
Wscript.Echo strUser & ";" & objList.Item(strUser)
End If
Next
' Clean up.
adoConnection.Close
这个脚本我们不要直接运行,否则我们只能看到屏幕多次弹出每个用户最后一次登录时间,我们把这个结果重定向到一个文件中去,执行下面步骤:
C:\>cscript lastlogon.vbs>lastlogon.csv
执行完毕生成一个CSV文件,打开此文件,可以看到最后1次登录时间,个人测试的结果文档内容如下:
从上图很容易看出最后一次登录时间,有些用户从来没有登录也会显示在上面。(如果想把最后一次登录时间作为独立一列分离出来,用Excel也非常容易实现,在此不再强调。)