Skip navigation

So recently we had to perform an AD cleanup of aged computer objects in our environment.  For a lot of companies this is a pretty standard procedure, for others, it’s just ignored (as was the case for us for a while).

Anyway, in the course of completing this task we had looked at a few scripts and tools that others had written/published around the internet and I inevitably got the bright idea to sit and write a tool for us to use in PowerShell.  So I setup my goals and fired up the old editor and went to work.


  • Identify aged objects
    • To identify aged objects, I went with the PasswordLastSet property of the object. There really isn’t a much better one to utilize, and it works off a 30 day cycle so it’s close enough.
  • Write out data for records
    • For write out I built a switch (–report) that will utilize the export-csv cmdlet to export a record of machines to the current users desktop.
  • Move objects to different OU
    • For moving objects I used the Move-ADObject cmdlet from the activedirectory module available with win 7 and server 2008 features.
  • Generic (no non standard add ins)
    • To keep it generic I chose to use the activedirectory module since we are running on 2008 servers, and migrating to windows 7. This insures future state usage, and prevents additional downloads or installs for functionality.
  • Modular (sometimes you just want a report)
    • To keep it modular, I built the (-move) switch. Unless the user explicitly defines this then the script will only report what was requested. Either to console output, or to a csv on the desktop (-report).
  • Versatile for targeting object date ranges and OUs
    • To insure versatility, I left 3 variables to be declared. $TIME, $TARGETR, $TARGETM. Date range, target OU to read, and Target OU to move respectively.
  • Script initially with potential to integrate in profile as a function
    • To build it as a standalone script, I originally had a (-help) switch that would output similar information as the get-help blah-blah –examples. Now with it functionized, I’ve removed that and added an overall function name to the code.

How it works:

Once applied to the PowerShell profile it can be called using get-adinactivecomputer.  By default it requires a date range either specified in <number>d for days or <number>y for years and a target OU to search from.  If these variables aren’t applied at the command line the function will request them at run time.

If –move and –report are specified then the function will need a target OU to move the items to and will generate a list with Object names and PasswordLastSet dates on the desktop and attempt to move them to the specified OU.  The switches must be declared at the command line but all variables are requested at run time if not stated before hand.

Now the nuts and bolts…..


First we check for the $TIME variable and request if it’s not present, then insure it’s in string format.  We’ll check that string for a d or a y to determine how to handle the string and then convert it to an appropriate integer value.  We’ll also bailout if we can’t distinguish the range (since this is a has the potential of causing serious AD harm we want to insure the user is accurate in their input).

Second we’ll check for the –report switch and if it’s present we’ll run the internal ADCLEANUP function and pipe it to export-csv $homedesktopinactivecomputers.csv.  If it’s not then we’ll just generate output to the console.  We pass the $TIME and $TARGETR variable to this function.

Third we check for the –move switch, and if it’s present run the internal function MOVEOLD and pass it the $TARGETM variable.

Fourth and final step, we nullify a global variable set during the ADCLEANUP function.



First step of the ADCLEANUP function is to insure the activedirectory module is loaded.  Next it verifies that a $TARGETR variable exists, if not it will prompt for one.  It then will take and search AD for the distinguished name of the OU provided. 

Next we build a date range variable using .Net Date Math.  We will subtract the total number of days by the integer value provided in $TIME from Today’s date and store that in $COMPARE. 

Now we declare a global variable $ADLIST that grabs all computer objects with PasswordLastSet property less than or equal to $COMPARE from the $TARGETR OU.

We then process those objects with a ForEach into a PSObject for reporting purposes specifying the Name and PasswordLastSet properties.  I did this mainly to guarantee a clean csv export.



The MOVEOLD function is fairly straight forward.  We check for the $TARGETM variable, if it doesn’t exist we prompt for an input.  We then build $TARGETM into a manageable string, then again we set it as a proper OU.  We run the $ADLIST through another ForEach statement and use Move-ADObject to relocate each $ITEM to $TARGETM.


I posted this script on the script center repository.  I didn’t build in any error catching which I should have, and plan to revisit that at a later date.  I enjoyed writing it so much I wanted to take some time to dissect it and discuss it a bit.  Hopefully this information proves useful to someone with similar goals and or general interest. 

For the the Microsoft.Powershell_profile.ps1 and Microsoft.PowershellISE_Profile.ps1 version of the script, perform the following steps in order:

Uncomment lines 4 and 193

Delete lines 7 through 50

Delete: ,[switch]$HELP from line 6

Delete line 46

Modify line 60 to read:                    `n`nTry get-help Get-InactiveADComputer -Examples`n";break}

One Comment

  1. Terrific, this facts is exactly what I was searching for. I am undoubtedly thankful to this topic because it assuredly gives useful information. Very well written blog. I look transmit to looking more. This blog is bookmarked! I positively love the stuff you have put here.

Leave a Reply