Guy's Scripting Ezine 86 - LastLogon Property - Part 2
Contents for Ezine 86 - LastLogon
Property
♣
If I had to give a man-of-the-match award to an element of this week's script, it would be a tie between WScript.Echo and the construction 'If...Then... End
If'. My secret for success was to combine WScript.Echo commands with the 'If' construction. As a result I was able to troubleshoot the more powerful sections, for example the sub routine to move the
computers or users. While I have 'Remmed out most of the WScript.Echo lines in the final script, I retained an unusually high number of 'If' statements. Incidentally, I don't know how I would have managed without my
OnScript VBScript editor, see here menu opposite. This week's script is a triumph for vision, believe and perseverance.
In truth, I had forgotten how
difficult it was to move an object from one OU to another using a script. Drag and drop is so easy in the MMC, but to mimic this action with a VBscript is very difficult. If I have a lingering doubt
about this week's script, it is that although this is a
beautiful script, even a work of art, it may not be suitable for teaching purposes.
Guy Recommends 3 Free Active Directory Tools
Solarwinds have produced three Active Directory add-ons. These free utilities
have been approved by Microsoft, and will help to manage your domain by:
- Seeking and zapping unwanted user accounts.
- Finding inactive computers.
- Bulk-importing new users. Give it a try.
Download your FREE Active Directory administration tools.
Five readers kindly wrote in suggesting that we disable the accounts before deleting them. I whole-heartedly agree. Last week I was so focussed on the lastLogon date that I forgot about 'best practice'.
In this instance, best practice is to disable the accounts, backup Active Directory, and only then delete the old accounts.
Now the above task is easy to plan, but hard to put into action, especially the section which moves the computer or user objects from one OU to another. I have extended my usual plea for you to break the
script into sections by introducing two sub-routines. Sub Disable() will handle disabling the
accounts, while the Sub MoveUser() moves the disabled user or computer accounts into another OU.
There are three goals for this script: 1) To identify all users or
computers that are older than 60 days. (Number of days is controlled by intAging.) 2) To disable these old accounts. 3) To move any disabled accounts into a separate OU. I admit that in terms of logic,
in a production network, this
could mean moving accounts that are disabled but not older than 60 days. My defence is that such points keep you on your toes, and that you or I could amend the script to cater for
this loophole. What I seek is to create scripts that teach you about scripting as well as solving specific problems. O.K. I confess, the real reason that I have not perfected the script is time, plus
a genuine wish not to add yet more complexity to the script. PrerequisitesThis 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. - Review how the script extracts the lastLogon date - See last week's ezine.
If necessary, create an extra test route to check the lastLogon value against the value for a known date.
- Decide what you want to do with objects that match the test, disable them? Move them, or even both?
- Talking of objects, you have a decision to make. Decide whether to run the script
for users, computers
or both.
Instructions for Creating a VBScript to display lastLogon time.
- You have not just one variable to amend, but a whole section. Make sure that you set the SourceOU, and the DestinationOU. Pay special attention to the type of object 'Computer' or 'Person'
(not user).
- Create a few new users and new computer in your SoureOU, as these account will never have logged on, they will have lastLogon value of 1/1/1601. As a result, the script will
identify, disable and then
move these accounts into strDestinationOU.
- Copy and paste the example script below into notepad or get a OnScript.
-
One advantage of a good script editor such as OnScript is that you can see the line numbers.
- Save the file with a .vbs extension, for example:
LastLogonMove.vbs
- Double click LastLogonMove.vbs and check the message box.
Calculating IP Address
ranges is a black art, which many network managers solve by creating custom
Excel spreadsheets. IPAT cracks this problem of allocating IP addresses
in networks in two ways:
For Mr Organized there is a nifty subnet
calculator, you enter the network address and the subnet mask, then IPAT
works out the usable addresses and their ranges.
For Mr Lazy IPAT
discovers and then displays the IP addresses of existing computers.
Download the Free IP Address Tracker
This example disables all accounts older than 60 days in an OU
specified by strSourceOU. It then
moves these filtered accounts into a named OU. Note my script's original version number was 5.1, I would not be surprised that in the light of feedback, I amended the script, if so check the version
number of the example below. ' LastLogonMove.vbs ' Example VBScript to display when an object last logged on ' Version 5.1 - September 2005 '
------------------------------------------------------------------' Option Explicit Dim objOU, objUser, objRootDSE, objLastLogon Dim strContainer, strDNSDomain, strMove, strLDAP Dim strLDAPQ, strQ,
arrClass, strPerson, strDisable Dim intLastLogonTime, intKeyDate, intAging, intDeleteDate
Dim objConnection, objCommand, objRecordSet, objNewOU, objMoveUser Dim strUser, strSourceOU,
strDestinationOU Dim intCounter, intDisabled, intMoved
intDisabled = 0 intMoved = 0 ' ----------------------------------------------------------' ' Note: Please change these variables to
reflect your domain ' ----------------------------------------------------------' intAging = 60 ' How old before delete? Number of days strSourceOU = "OU=Accounts, " strDestinationOU = "OU=PayRoll,"
strDisable = lcase("Computer") 'Computer or Person (not User) ' ----------------------------------------------------------- ' Binding to Active Directory. Note strSourceOU Set objRootDSE =
GetObject("LDAP://RootDSE") strDNSDomain = objRootDSE.Get("DefaultNamingContext") strDNSDomain = strSourceOU & strDNSDomain set objOU =GetObject("LDAP://" & strDNSDomain ) '
---------------------------------------------------------- ' Section to calculate variables for the MoveUser() Sub ' Getting the speech marks around the LDAP names is tricky. strQ = "'" & strDisable &
"'" strLDAPQ = "'LDAP://" & strDNSDomain & "'" ' Extra comma is needed for strSourceOU but not strDestinationOU ' This comma drove me mad. strSourceOU = "," & strSourceOU &
objRootDSE.Get("DefaultNamingContext") strDestinationOU = strDestinationOU & objRootDSE.Get("DefaultNamingContext") ' --------------------------------------------------------------- For Each objUser In
objOU Set objLastLogon = objUser.Get("lastLogon") intLastLogonTime = objLastLogon.HighPart * (2^32) + objLastLogon.LowPart intLastLogonTime = intLastLogonTime / (60 * 10000000) intLastLogonTime =
intLastLogonTime / 1440
' Key date test statement. Are they older than intAging? intDeleteDate = date()-intAging intKeyDate ="#" & intDeleteDate & "#" ' Wscript.Echo "Date for deletion " &
intKeyDate ' Check date calculation if intKeyDate > intLastLogonTime Then ' Call the subroutines Disable(), then MoveUser() Call Disable() if objUser.userAccountControl = 514 Then Call MoveUser()
End if if objUser.Name <> "" then Wscript.Echo objUser.Name & " 's last logon time: " _ & intLastLogonTime + #1/1/1601# End if End if Next WScript.Echo intDisabled & " Accounts disabled"
_ & vbcr & intMoved & " Accounts moved " WScript.Quit
' Sub Routines Section
Sub Disable() ' Note use of objCategetory not objClass. Heavy use of Split. If objUser.userAccountControl
<> 514 then arrClass = split(objUser.objectCategory,",") strPerson = split(arrClass(0),"=") strPerson(1) = lcase(strPerson(1)) ' Wscript.Echo "strLDAP " & strPerson(1) ' If we have the right type
of object, then disable. If strPerson(1) = strDisable then objUser.Put "userAccountControl", 514 objUser.SetInfo Wscript.Echo objUser.name & " is disabled " & strPerson(1) intDisabled =
intDisabled + 1 End if End if
End sub
Sub MoveUser() ' MoveUser.vbs - A very difficult routine ' -----------------------------------------------------------------' ' This is a
tricky section. Makes a new link to Active Directory Const ADS_SCOPE_SUBTREE = 2 Set objConnection = CreateObject("ADODB.Connection") Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject" objConnection.Open "Active Directory Provider" Set objCOmmand.ActiveConnection = objConnection '
-----------------------------------------------------------------' objCommand.CommandText = _ "Select Name, Location from " & strLDAPQ _ & "where objectCategory=" & strQ objCommand.Properties("Page
Size") = 1000 objCommand.Properties("Timeout") = 30 objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE objCommand.Properties("Cache Results") = False
' Treats the User objects as a set
of record cards Set objRecordSet = objCommand.Execute if objRecordSet.EOF <> True Then objRecordSet.MoveFirst End if ' Get all the records Do Until objRecordSet.EOF
strUser =
objRecordSet.Fields("Name").Value strUser = "CN="& strUser ' This script features lots of IFs. This look ensures only ' disabled accounts, which match the user name get moved. if objUser.name =
strUser then if objUser.userAccountControl = 514 then ' Wscript.Echo "User Name: " & strUser & vbcr & objUser.name Set objNewOU = GetObject("LDAP://" & strDestinationOU) Set objMoveUser =
objNewOU.MoveHere _ ("LDAP://" & strUser & strSourceOU, strUser) intMoved = intMoved +1 End if End if objRecordSet.MoveNext
Loop
End Sub
' End of disable then move accounts
VBScript
Learning PointsNote 1: Firstly, seek information from Remarks in the actual script. Note 2: Refresh your memory of the lastLogon
attribute in Ezine 85. Note 3: The secret of understanding this script is to break it down into four sections. Note 3a: Amend your variables, beginning with intAging at line 20. Note
3b: Check the logic of comparing lastLogon with intKeyDate lines 46-59 Note 3c: Realize that userAccountControl = 514 means disable the account. Note 3d: Examine the MoveUser() sub Routing in great detail.
Note 4: Make a point of finding, and understanding each of the 'If...Then...End If' constructions. Note 5: Make a special study of objectCategory line 71 because you can use
the 'Person' value in other VBScripts. ObjectCategory
is a different LDAP property from objectClass and I use it to distinguish between users and computers. You could substitute objectClass, but be aware that 'User' is a value of both Users and Computers. Strange but
true. The benefit of objectClass is that you can filter with 'Computer' and 'Person'. Remember that 'Person' is a value held only by User objects. (Check with ADSI Edit). Note 6:
I have been smitten with the Split() function, and I employ it here to extract the 'Person' or 'Computer' value from the objectCategory. It goes without saying that there are other ways of filtering
the objects, but I am taken with Split, and that is what I used to select one type of Active Directory account. Note 7: As I hinted earlier, I had forgotten that scripting the process to move users was
so difficult. Regard Sub MoveUser() (line 87) as a 'black' box for shovelling disabled objects into a holding pen. In real life, the idea would be to examine them and check that they were the
correct object before running another script to delete these old users or computers. Note 8: This script also features a one-liner to get today's date. Examine the simple but effective date
function and see why the script always detects accounts that are older than 60 days from when you run the script. See line 47: intDeleteDate = date()-intAging
This is an advanced script. It's goals are to identify old Active Directory accounts, disable them and finally to move the User or Computer accounts to a different OU. The second OU acts as a holding pen until you are ready to delete
these old objects.
See More Active Directory VBScripts for Passwords
• User Spreadsheet • Add Users to Groups • Create
Users • Free
CSV Importer
• Ezine 83 Passwords •
Ezine 85 LastLogon • Ezine
86 LastLogon • Ezine 122 Passwords
• Ezine 128 IUSR Passwords •
VBScript change
password • Tool Kit • Ezines
|