Solved

script to disable stale computer accounts

Posted on 2009-05-11
5
2,302 Views
Last Modified: 2012-06-09
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

0
Comment
Question by:smdc_ia
5 Comments
 
LVL 57

Expert Comment

by:Mike Kline
ID: 24361642
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
 
LVL 70

Expert Comment

by:Chris Dent
ID: 24362388

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
 
LVL 70

Accepted Solution

by:
Chris Dent earned 500 total points
ID: 24363949

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
 

Author Closing Comment

by:smdc_ia
ID: 31580389
Excellent! Thanks for quick and accurate response.
0
 

Expert Comment

by:cgooden01
ID: 25403557
On this particular thread, Is there a way using oldcmp to filter just the computer objects in your domain
0

Featured Post

Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

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

Not long ago I saw a question in the VB Script forum that I thought would not take much time. You can read that question (Question ID  (http://www.experts-exchange.com/Programming/Languages/Visual_Basic/VB_Script/Q_28455246.html)28455246) Here (http…
Restoring deleted objects in Active Directory has been a standard feature in Active Directory for many years, yet some admins may not know what is available.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

920 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now