Need Script for last logon times of user accounts that are members of a specific security group

crphd
crphd used Ask the Experts™
on
Hi All,
I need a script that will gather the last logon time for user accounts that are members of a specific security group.  Preferably the time stamp would be how many days since last logon. Need this one rather quick so willing to give the extra points.  Thanks for all your help,
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2013

Commented:
I like using adfind by Joe Richards for this

http://www.joeware.net/freetools/tools/adfind/index.htm


adfind -default -f "&(objectcategory=person)(objectclass=user)(memberof=DN of your group)"  samaccountname lastlogontimestamp -tdc -csv > c:\groupmembers.csv

if you have nested group members then adfind can be used for that too, more on that here:  http://adisfun.blogspot.com/2009/06/find-group-members.html

I'm off to work but should be able to respond to follow ups at lunch.

Thanks

Mike
bluntTonyHead of ICT
Top Expert 2009

Commented:
Hi there,

Just to add the functionality of showing the days since last logon, something which I'm not sure adfind can do without extra scripting, the below VBS script will output a CSV file with the user name, last logon and days since last logon.

Add the DN of the group in question to line 9

Date calculations pinched from here : http://www.rlmueller.net/Programs/LastLogonTimeStamp.txt

Output it to a CSV e.g.

cscript getUsers.vbs > results.csv

If you need this embellishing let us know.

Tony

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

strGroupDN = "YOUR GROUP DN HERE"

strBase   =  "<LDAP://" & oRootDSE.get("defaultNamingContext") & ">;"
strFilter = "(&(objectclass=user)(objectCategory=person)(memberof=" & strGroupDN & ");" 
strAttrs  = "distinguishedName,cn,lastlogonTimeStamp;"
strScope  = "subtree"
objComm.CommandText = strBase & strFilter & strAttrs & strScope
Set objRS = objComm.Execute

If objRS.RecordCount > 0 Then
	objRS.MoveFirst
	WScript.Echo "Name,LastLogonTimeStamp,Days Since Last Logon"
	Do Until objRS.EOF
		On Error Resume Next
	    Set objDate = objRS.Fields("lastLogonTimeStamp").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
	    ' Display values for the user.
	    If (dtmDate = #1/1/1601#) Then
	        strLastLogon = "Never"
	    Else
	        strLastLogon = dtmDate
	    End If
		On Error Goto 0
		objRS.MoveNext
		WScript.Echo objRs.Fields("cn") & "," & strLastLogon & "," & DateDiff("d",dtmDate,Date())
	Loop
End if

Open in new window

Author

Commented:
Thank you all for your responses, I will be working with them for the next couple of hours or so.

Author

Commented:
Sorry bluntTony, but I am recieving an error message when i run: C:\>cscript VBSname.vbs> Results.csv.  It mentions (16,1) error.  When I look at your script, I don't see an issue with line 16, character 1.  
I changed the DN to the appropriate format (cn=sec group,ou=groups,etc.)
Any suggestions?
Head of ICT
Top Expert 2009
Commented:
My bad. Typo in line 12. Now fixed below.

It is also worth noting that lastLogonTimeStamp isn't 100% accurate. While it is replicated to all DCs when it's updated, it's not actually always updated.More information on how AD decides whether or not to update the attribute here : http://blogs.technet.com/askds/archive/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works.aspx

The reason for this is to reduce replication load on DCs for busy domains. I'm pretty sure this will affect the results from adfind and from this script. The alternative to this is to query each DC's event logs to get the last logon event for each user. This would be more 'real time' although this would be pretty tricky without 3rd party software.

However if the purpose of the script is to track old accounts that haven't been used over a period of time, then this method might be OK for you.

Tony

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

strGroupDN = "cn=domain admins,cn=users,dc=domain,dc=local"

strBase   =  "<LDAP://" & oRootDSE.get("defaultNamingContext") & ">;"
strFilter = "(&(objectclass=user)(objectCategory=person)(memberof=" & strGroupDN & "));" 
strAttrs  = "distinguishedName,cn,lastlogonTimeStamp;"
strScope  = "subtree"
objComm.CommandText = strBase & strFilter & strAttrs & strScope
Set objRS = objComm.Execute

If objRS.RecordCount > 0 Then
	objRS.MoveFirst
	WScript.Echo "Name,LastLogonTimeStamp,Days Since Last Logon"
	Do Until objRS.EOF
		On Error Resume Next
	    Set objDate = objRS.Fields("lastLogonTimeStamp").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 (dtmDate = #1/1/1601#) Then
	        strLastLogon = "Never"
	        strDaysSince = "N/A"
	    Else
	        strLastLogon = dtmDate
	        strDaysSince = DateDiff("d",dtmDate,Date())
	    End If
	    On Error Goto 0
	    WScript.Echo objRs.Fields("cn") & "," & strLastLogon & "," & strDaysSince
	    objRS.MoveNext
	Loop
End if

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial