PowerShell Ezine, Logon Scripts

Guy's Scripting Ezine 85 - LastLogon Property

Contents for Ezine 85 - LastLogon Property

This week's secret

I have a dilemma.  Four readers have requested a script that will assist them to delete users.  They want to clean up Active Directory based on time since the last logon.  My problem is that I don't like and I don't trust the lastLogon LDAP property, which is required for such a script.  To return to my dilemma, do I ignore lastLogon, or do I help readers by creating a script?

Here is what I am going to do, set out my concerns about lastLogon, then give you a script which works OK for me.  I seek a compromise between explaining how to detect old objects with VBScript, yet warn you of the inherent pitfalls of such a script.


If you are looking for handy network utilities, try some of the free downloads at Tools4Ever


Scenario: You want to Identify Old User or Computer Accounts

Administrators want to delete old accounts, this is a worthy goal.  If a user never joined the organization, or a computer has been thrown out, then the corresponding account only clutters up Active Directory.

My recipe for success is to break down a complex script into manageable scriplets, get each part working and then join them all together.  Therefore, let us take a step backwards and analyse the four steps need to achieve our goal of deleting old accounts.

  1. Enumerate the lastLogon date for all objects in an OU
  2. Filter those users with old accounts
  3. Move the accounts to a holding OU
  4. Check then delete the accounts

 

This week's scripts seek solely to achieve point 1. To list the lastLogon date for objects in an OU.  Next week I will tackle filtering and moving Active Directory objects such as users.

Beware lastLogon

Time to explain what Guy can possibly have against manipulating old accounts with the lastLogon LDAP property.

0) Creating any script which deletes Active Directory objects, puts me under extra pressure.  What if, despite testing,  my script goes wrong and deletes the wrong objects in your domain?

1) My research reveals that Active Directory stores the lastLogon attribute as Integer8 (8 bytes). This means lastLogon is stored as a 64-bit number, the problem is that VBScript cannot handle 64-bit numbers directly.  Fortunately, there is a work around, namely, to treat lastLogon as an object, and then assign it HighPart and LowPart values.

To digress, the ace stock picker Warren Buffett once said, 'Never invest in a company whose workings you cannot understand'.  Guy says, 'Never invest in an LDAP property whose workings you do not fully comprehend'.  My problem is that I have not met anyone who can explain to my satisfaction the maths and logic of HighPart and LowPart.  Yes, it worked in my example, but I did not truly understand why.

2) My best maths skill is estimating, I always know roughly how much the shopping will cost, I can guess to within one gallon how much petrol I need to fill my tank.  When it comes to estimating how many 100 nanosecond slices there are in a year, I have no idea.  Perhaps I should have mentioned earlier, lastLogon measures 100 nanosecond time slices since January 1st 1601.  I believe this time base is known as (UTC) Universal Time Co-ordination.  My point is that I cannot rely on my usual estimation skills to work out if I have made an arithmetic mistake.  (Are there 10000000 nanoseconds in a second, or is it 10000000?) 

Just in case you think I am a maths dunce, I am able to calculate, that depending when you read this, there are approx 147803 days since January 1601.  You may detect I am having a cathartic moment, so here is another of my irritations - numbers without thousand separators.  To my way of thinking, the number of days should display as 147,803 in English. (147.803 in American?)   Is my irritation with large numbers without separators an age factor, or is it an English phenomenon?  Do tell me what you think.

3) The next problem, which is going to affect some readers, is the date format.  The fact that the majority of readers have dateline offset from GMT of just a few hours, probably won't matter.  However, a more serious worry is that the lastLogon calculation relies on the date format.  Specifically, there is more than one time format, the USA use: mm-dd-yy, whereas, the UK uses the format dd-mm-yy.  Again, my gut instinct is the format will be consistent for all domain controllers thus will not matter, but a lingering doubt remains in my mind.

4) There is one more banana skin waiting to trip you up.  LastLogon is one of the few Active Directory objects that is not replicated between domain controllers.  I'm lucky in that I only had one Domain Controller in my test domain, but this does not reflect real life.  I can foresee a potential disaster that unless you query all domain controllers, you could easily come to the wrong conclusion.  One Domain Controller could report that a given user never logged on, only to find out that they had indeed logged on elsewhere.  Meanwhile, you could have deleted the user on the basis of my lastLogon script.

In summary, if a script has one imperfection, then I can forgive it, but when I get 4 or 5 niggles, I start to worry about a scripts reliability.

ˆ

Script to Identify Dormant User and Computer Accounts

The goal of this script is to display the time when each object last logged on.  In case you get swamped with data, I suggest you start with one, named OU.  Later you could amend the script to point to CN=Users, (not OU=Users,).

Prerequisites

This script needs an Active Directory domain, however please note that for safety, this script is designed for a domain with only one Domain Controller.  Best would be to logon as administrator at a domain controller.  My plan B would be to Remote Desktop to a domain controller.

Instructions for Creating a VBScript to display lastLogon time.

  1. Decide upon the OU where you want to enumerate accounts, this is vital.  (I choose OU=Droitwich, note the comma.)
  2. Copy and paste the example script below into notepad or use a VBScript editor.
  3. One advantage of a good script editor such as OnScript is that you can see the line numbers (See menu on the upper left for free copy).
  4. Save the file with a .vbs extension, for example: lastLogon.vbs 
  5. Double click lastLogon.vbs and check the message box.

 

ˇ

Example - To Reset All Passwords in a Named OU.

This example displays the lastLogon LDAP attribute for all object in a named OU.

 

' LastLogon.vbs
' Example VBScript to display when an object last logged on
' Version 2.0 - August 2005
' ---------------------------------------------------------'
Option Explicit
Dim objOU, objUser, objRootDSE, objLastLogon
Dim strContainer, strDNSDomain
Dim intLastLogonTime, intGuyTime
' --------------------------------------------------------'
' Note: Please change OU=Droitwich, to reflect your domain
' --------------------------------------------------------'
strContainer = "OU=Droitwich, "

Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")

strContainer = strContainer & strDNSDomain
set objOU =GetObject("LDAP://" & strContainer )
For Each objUser In objOU
Set objLastLogon = objUser.Get("lastLogon")
intLastLogonTime = objLastLogon.HighPart * (2^32) + objLastLogon.LowPart
intLastLogonTime = intLastLogonTime / (60 * 10000000)
intLastLogonTime = intLastLogonTime / 1440

Wscript.Echo objUser.givenName & " 's last logon time: " _
& intLastLogonTime + #1/1/1601#
Next
WScript.Quit

' End of lastLogon example VBScript

 

Learning Points

Note 1: There are 10000000 (Ten million) 100 nanosecond slices in a second.  The 60* refers to the number of seconds in a minute.  I expect that you have worked out that 1440 refers to the number of minutes in a day.

Note 2: UTC time starts in 1601, remember the hash (#) in the formula + #1/1/1601#.  My calculations show there have been approx 147803 days since the beginning of UTC time in January 1601.

LastLogon Challenges

For a production script, you would probably need to filter either the object so that it returned Users, or Computers but not both.  Another filtering method that springs to mind is displaying only accounts that have not logged on since a specified date.

Both these challenges will be picked up in next week's ezine, but if you wanted to experiment then feel free to amend my script, because it's only by changing my script that you will truly understand lastLogon.

Summary of lastLogon date

Clearing up old accounts, or user objects that never have and never will logon is good housekeeping.  The best LDAP property is lastLogon, however, before you take action and delete accounts, check that the results are as expected.  Perhaps the most insidious problem is that lastLogon is not replicated amongst your domain controllers.

Computer Training Software - Recommended Training VideosGuy Thomas recommends Computer Training Software

Their topics and material are ideal for getting you started with VBScript.  The videos are easy to follow and you can control the pace.  Try their free demo material and then see if you want to buy the full package. See more about VB Script Training CD.


 *


Google

Webcomputerperformance.co.uk

GFi Events Manager

Guy Recommends: GFi EventsManager

Here is a solution to monitor, manage and archive thousands of events that are generated by devices across your entire network.  Get your free evaluation copy of GFI EventsManager.

 

Home Copyright © 1999-2008 Computer Performance LTD All rights reserved

Please report a broken link, or an error.