Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Automated removal of expired machines in Active Directory

Posted on 2009-07-02
7
Medium Priority
?
416 Views
Last Modified: 2013-12-05
I'm looking for a way to automate the removal of expired machines (not logged in > 90 days) to help with asset management.
0
Comment
Question by:Al Caholic
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
7 Comments
 
LVL 13

Accepted Solution

by:
Brum07 earned 500 total points
ID: 24763426
0
 
LVL 38

Assisted Solution

by:Shift-3
Shift-3 earned 500 total points
ID: 24763445
If your domain is at the 2003 functional level or higher then you can find inactive computers using the command
dsquery computer -inactive <number of weeks>

Run this from a 2003 server or an XP machine with the adminpak installed.

You could pipe the output of this command to dsrm to delete the accounts, but do so with extreme caution.
0
 
LVL 57

Assisted Solution

by:Mike Kline
Mike Kline earned 500 total points
ID: 24763534
I really like old computer by MVP Joe Richards for this
http://www.joeware.net/freetools/tools/oldcmp/index.htm
Very nice reports that managment likes too.  
start with
oldcmp -report

Thanks
Mike
0
 
LVL 12

Expert Comment

by:mlongoh
ID: 24763610
I've written vbscripts to query the last logon date of a computer's object (depending on the forest and domain operational level, you might have to query each domain controller or if you are running at 2003 native then you can query AD directly) and then based on the results you can delete the objects that are old - or move them to an expired OU and then delete them once they are really old. It's up to you.

The code for getting last logon is somewhat complex, but I will attach it shortly in a subsequent post.

Deleting the object from AD via vbscript is pretty easy:


strComputer = "atl-pro-040"
set objComputer = GetObject("LDAP://CN=" & strComputer & ",CN=Computers,DC=fabrikam,DC=com")
objComputer.DeleteObject (0)

Open in new window

0
 
LVL 12

Assisted Solution

by:mlongoh
mlongoh earned 500 total points
ID: 24763836
Here's a script that will poll each DC in the domain and determine the most recent last logon date of the computer and output that and whether the computer is enabed or disabled. It expects you to enter the computer name as a command line argument when running the script. You can use pieces of this script and the other small snippet I posted for deleting objects to create one that does the job you want.


On Error Resume Next
Const ADS_UF_ACCOUNTDISABLE = 2
 
strPath = left(wscript.ScriptFullName, len(wscript.ScriptFullName) - len(wscript.ScriptName))
 
strDom = "fabrikam"
Const ADS_SCOPE_SUBTREE = 2
 
'Find DN
strNTName = strDOM & "\" & wscript.arguments(0) & "$"
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_NT4 = 3
Const ADS_NAME_TYPE_1779 = 1
Set objTrans = CreateObject("NameTranslate")
objTrans.Init ADS_NAME_INITTYPE_GC, ""
objTrans.Set ADS_NAME_TYPE_NT4, strNTName
' Use the Get method to retrieve the RPC 1779 Distinguished Name.
strPCDN = objTrans.Get(ADS_NAME_TYPE_1779)
strPCDN = Replace(strPCDN, "/", "\/")
 
wscript.echo strPCDN
LastLog = #1/1/1601#
 
'Get TimeZone offsets
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colTimeZones = objWMIService.ExecQuery("Select * From Win32_TimeZone")
For Each objTimeZone in colTimeZones
intTimeZoneBias = objTimeZone.Bias
intDaylightBias = objTimeZone.DaylightBias
Next
 
Set objRootDSE = GetObject("LDAP://RootDSE")
strConfigurationNC = objRootDSE.Get("configurationNamingContext")
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
 
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
 
objCommand.CommandText = _
"SELECT ADsPath FROM 'LDAP://" & strConfigurationNC & "' WHERE objectClass='nTDSDSA'" 
Set objRecordSet = objCommand.Execute
 
objRecordSet.MoveFirst
 
'Get lastlogon from each DC and find newest
Do Until objRecordSet.EOF
Set objParent = GetObject(GetObject(objRecordset.Fields("ADsPath")).Parent)
strDCName = objParent.dnsHostName
 
Set objUser = GetObject _
("LDAP://" & strDCName & "/" & strPCDN)
 
Set objLastLogon = objUser.Get("lastLogon")
Set objLastLogonTS = objUser.Get("lastLogonTimestamp")
 
intLastLogonTime = objLastLogon.HighPart * (2^32) + objLastLogon.LowPart 
intLastLogonTime = intLastLogonTime / (60 * 10000000)
intLastLogonTime = intLastLogonTime / 1440
 
dtmLastLogon = intLastLogonTime + #1/1/1601#
dtmLastLogon = DateAdd("n", intTimeZoneBias, dtmLastLogon)
dtmLastLogon = DateAdd("n", intDaylightBias, dtmLastLogon)
 
intLastLogonTimeTS = objLastLogonTS.HighPart * (2^32) + objLastLogonTS.LowPart 
intLastLogonTimeTS = intLastLogonTimeTS / (60 * 10000000)
intLastLogonTimeTS = intLastLogonTimeTS / 1440
 
dtmLastLogonTS = intLastLogonTimeTS + #1/1/1601#
dtmLastLogonTS = DateAdd("n", intTimeZoneBias, dtmLastLogonTS)
dtmLastLogonTS = DateAdd("n", intDaylightBias, dtmLastLogonTS)
 
wscript.echo " " & strDCName & " reports " & dtmLastLogon & " as last logon"
wscript.echo " " & strDCName & " reports " & dtmLastLogonTS & " as last logonTimeStamp"
 
If dtmLastLogonTS > dtmLastLogon Then dtmLastLogon = dtmLastLogonTS
 
If dtmLastLogon > LastLog Then
LastLog = dtmLastLogon
End If
 
objRecordSet.MoveNext
Loop
wscript.echo "Final choice = " & LastLog
 
If Instr(LastLog, " ") > 0 Then
LLArray=Split(LastLog, " ")
LastLog=LLArray(0)
End If
 
AcctStatus1=objUser.userAccountControl
If AcctStatus1 AND ADS_UF_ACCOUNTDISABLE Then
AccountStatus = "disabled"
Else
AccountStatus = "enabled"
End If
 
wscript.echo wscript.arguments(0) & ";" & strPCDN & ";" & LastLog & ";" & AccountStatus
 
wscript.quit
 
'Functions
Function IsAccountDisabled( strDomain, strAccount )
Dim objUser
Set objUser = GetObject("WinNT://" & strDomain & "/" & strAccount & ",user")
IsAccountDisabled = objUser.AccountDisabled
End Function 

Open in new window

0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Always backup Domain, SYSVOL etc.using processes according to Microsoft Best Practices. This is meant as a disaster recovery process for small environments that did not implement backup processes and did not run a secondary domain controller that ne…
Auditing domain password hashes is a commonly overlooked but critical requirement to ensuring secure passwords practices are followed. Methods exist to extract hashes directly for a live domain however this article describes a process to extract u…
This tutorial will walk an individual through the process of configuring their Windows Server 2012 domain controller to synchronize its time with a trusted, external resource. Use Google, Bing, or other preferred search engine to locate trusted NTP …
Are you ready to implement Active Directory best practices without reading 300+ pages? You're in luck. In this webinar hosted by Skyport Systems, you gain insight into Microsoft's latest comprehensive guide, with tips on the best and easiest way…
Suggested Courses

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question