script to disable stale computer accounts

Has anyone written a script to disable computer accounts that have not communicated with the domain in x days? I have a powershell script that outputs the computers by name, date last logged into domain and # of days. I'd like to add the functionality to have AD disable these accounts. Any ideas. Below is the script I have, can't take credit it for it, I found it on a powershell wiki, but I don't remember which one, so kudo's if the author recognizes his/her work.
function Get-DomainComputerAccounts{ 
# Use Directory Services object to attach to the domain    
$searcher = new-object DirectoryServices.DirectorySearcher([ADSI]"")        
# Filter down to computer accounts    
$searcher.filter = "(&(objectClass=computer))"
# Cache the results    
$searcher.CacheResults = $true
$searcher.SearchScope = Subtree    
$searcher.PageSize = 1000        
#Find anything you can that matches the definition of being a computer object    
$accounts = $searcher.FindAll()        
# Check to make sure we found some accounts    
if($accounts.Count -gt 0)    {
foreach($account in $accounts)        {           
 # Property that contains the last password change in long integer format
$pwdlastset = $account.Properties["pwdlastset"];
# Convert the long integer to normal DateTime format
$lastchange = [datetime]::FromFileTimeUTC($pwdlastset[0]);
# Determine the timespan between the two dates
$datediff = new-TimeSpan $lastchange $(Get-Date);                   
 #Create an output object for table formatting            
$obj = new-Object PSObject;                        
# Add member properties with their name and value pair            
$obj | Add-Member NoteProperty ComputerName($account.Properties["name"][0]);            
$obj | Add-Member NoteProperty LastPasswordChange($lastchange);
$obj | Add-Member NoteProperty DaysSinceChange($datediff.Days);
# Write the output to the screen 
Write-Output $obj;
}    
       }
               } 
# Get computer accounts where a password change hasn't occurred in 60 days or more
# If nothing outputted, then there are no accounts that meet that criteria
Get-DomainComputerAccounts |Where-Object {$_.DaysSinceChange -gt 60}

Open in new window

smdc_iaAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
Chris DentConnect With a Mentor PowerShell DeveloperCommented:

Sorry dude I totally missed off the disable part...

It may be beneficial to modify each filter so it doesn't return previously disabled computers as well and you may want to specify a search base in each instance (at the moment that's $Null in the Directory Searcher).

To exclude disabled accounts in the search add this into the filter:

(!userAccountControl:1.2.840.113556.1.4.803:=2)

e.g.

$LdapFilter = "(&(objectClass=computer)(pwdLastSet<=$InactiveFrom)(!pwdLastSet=0)(!userAccountControl:1.2.840.113556.1.4.803:=2))"

Then you don't have to worry about the script finding and attempting to disable an account twice.

Disabling is done using a Bitwise OR change on the userAccountControl attribute (which is just a collection of flags).

Chris
$InactiveDays = "60"
$InactiveFrom = [Math]::Round(( `
  New-TimeSpan $(Get-Date("01/01/1601 00:00:00")) `
  ((Get-Date).AddDays(-$InactiveDays))).TotalSeconds, 0)
 
$InactiveFrom = "$($InactiveFrom.ToString())0000000"
 
# With http://www.quest.com/powershell/activeroles-server.aspx
 
$LdapFilter = "(&(pwdLastSet<=$InactiveFrom)(!pwdLastSet=0))"
 
# Returning the old computers using the filter 
$OldComputers = Get-QADComputer -LdapFilter $LdapFilter -IncludedProperties pwdLastSet | `
  Select-Object Name, pwdLastSet, DN
 
# Disabling each computer
$OldComputers | %{
  Set-QADObject $_.DN `
    -ObjectAttributes @{userAccountControl = $_.userAccountControl -BOr 2}
}
 
# Or with the Directory Searcher
 
$LdapFilter = "(&(objectClass=computer)(pwdLastSet<=$InactiveFrom)(!pwdLastSet=0))"
 
# Returning the old computers using the filter
$OldComputers = (New-Object `
  System.DirectoryServices.DirectorySearcher($Null, $LdapFilter)).FindAll() | `
  Select-Object `
    @{n='Name';e={ $_.Properties["name"] }}, `
    @{n='PwdLastSet';e={ [DateTime]::FromFileTimeUTC($($_.Properties["pwdlastset"])) }}, `
    @{n='DN';e={ $_.Properties["distinguishedname"] }}
 
# Disabling each computer
$OldComputers | %{
  $Computer = [ADSI]"LDAP://$($_.DN)"
  $Computer.Put("userAccountControl", $($Computer.Get("userAccountControl")) -BOr 2)
  $Computer.SetInfo()
}

Open in new window

0
 
Mike KlineCommented:
Won't blow smoke here,  I'm not sure about powershell for doing this (I'm sure it does it though)
Have you looked at oldcmp by Joe Richards for this
http://www.joeware.net/freetools/tools/oldcmp/index.htm
http://www.joeware.net/freetools/tools/oldcmp/usage.htm
 
 It produces a nice report
oldcmp -report
that will give you a report of all computers > 90 days
There are a ton of options and it can also be used for users
Thanks
Mike
0
 
Chris DentPowerShell DeveloperCommented:

OldCmp is rather good and worthy of consideration :)

But if you're sticking with PowerShell...

I would make the LdapQuery return the desired results rather than sorting through after returning everything.

For example, you're interested in devices which have been "inactive" for 60 days. I would build the LDAP Query as demonstrated in the example below.

Chris
$InactiveDays = "60"
$InactiveFrom = [Math]::Round(( `
  New-TimeSpan $(Get-Date("01/01/1601 00:00:00")) `
  ((Get-Date).AddDays(-$InactiveDays))).TotalSeconds, 0)
 
$InactiveFrom = "$($InactiveFrom.ToString())0000000"
 
# With http://www.quest.com/powershell/activeroles-server.aspx
 
$LdapFilter = "(&(pwdLastSet<=$InactiveFrom)(!pwdLastSet=0))"
 
Get-QADComputer -LdapFilter $LdapFilter -IncludedProperties pwdLastSet | `
  Select-Object Name, pwdLastSet, DN
 
# Or with the Directory Searcher
 
$LdapFilter = "(&(objectClass=computer)(pwdLastSet<=$InactiveFrom)(!pwdLastSet=0))"
 
(New-Object System.DirectoryServices.DirectorySearcher($Null, $LdapFilter)).FindAll() | `
  Select-Object `
    @{n='Name';e={ $_.Properties["name"] }}, `
    @{n='PwdLastSet';e={ [DateTime]::FromFileTimeUTC($($_.Properties["pwdlastset"])) }}, `
    @{n='DN';e={ $_.Properties["distinguishedname"] }}

Open in new window

0
 
smdc_iaAuthor Commented:
Excellent! Thanks for quick and accurate response.
0
 
cgooden01Commented:
On this particular thread, Is there a way using oldcmp to filter just the computer objects in your domain
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.