- Add a domain user or group to local administrators with PowerShell - Wed, Mar 19 2014
- Create a list of local administrators with PowerShell - Wed, Mar 5 2014
- Remotely query user profile information with PowerShell - Tue, Nov 26 2013
We can determine how old a computer object is, by looking at the PwdLastSet property of the computer account. This property holds the date and time that the password for this account was last changed in active directory. By default, a computer account updates its password in active directory every 30 days. That means, if a computer object’s last password update time is older than 30 days, then we can determine that the computer is inactive or not in use.
This may not be true if you have computers that don’t frequently connect to your corporate network and talk to active directory (ex: laptops), or computers that were shutdown intentionally for long time (lab systems/training lab systems). If any of those computers comes online after long time, they can still update their password. For more information please refer to this blog post.
In my script, I am using the PwdLastSet property to determine how old a computer object is. This script will query all computers in active directory, calculate the age of the computers objects, filter the computers that are older than a given number of days, and then move them to separate specified Organization Unit (OU). This script takes two arguments as described below.
Script inputs
- OlderThan: This argument indicates the inactivity period of computers that you want to query. For example, if you want to determine any computer that didn’t contact active directory for 60 days and treat it as inactive computer, then enter a value of 60 to this argument.
- TargetOU: This argument takes DN value of an Organization Unit in active directory to which you want to move old computers.
The script has Parameter validation enabled for TargetOU parameter so that it determines if the given OU exists or not before processing any computers.
param( [int] $OlderThan = 20, [ValidateScript({[ADSI]::Exists("LDAP://$_")})] [string]$TargetOU )
The ActiveDirectory module is used to query active directory computers and move them to designated OU. This module comes by default when you install Active Directory Services on Windows Serve 2008 R2 or Windows Server 2012. You can also manually install this module on Windows Server 2008 R2 and Windows 7 Computers by installing Remote Server Administration Tools feature. Since this feature is not available on Windows Server 2003, Windows XP computers, you cannot use this script from aforementioned Operating Systems. Please refer to TechNet for more details on how to install Active Directory Modules.
Use cases
The below command will help you to get the list of computers older than 30 days. Since it has a -WhatIf parameter, it doesn’t actually move the computer but will specify the operation that it is intended to perform.
.\Move-OldComputers.ps1 -OlderThan 30 -TargetOU "OU=OldComps,DC=TechiBee,DC=Com" -WhatIf
Get list of computers older than 30 days and move to TargetOU, use below command. It will prompt for your confirmation before moving computers to given OU.
.\Move-OldComputers.ps1 -OlderThan 30 -TargetOU "OU=OldComps,DC=TechiBee,DC=Com"
If you don't want to have confirmation message for each computer move, then first use -Whatif to review the list of computers that will get moved and then use below command to perform actual option without confirmation prompts.
.\Move-OldComputers.ps1 -OlderThan 30 -TargetOU "OU=OldComps,DC=TechiBee,DC=Com" -Confirm:$false
The reason I am moving old computers to an OU is that, you will have an option to review the old computers list in the target OU and perform bulk actions like disable or delete in a single click by selecting them all from Active Directory Users and Computers.
Subscribe to 4sysops newsletter!
PowerShell script
param( [int] $OlderThan = 20, [ValidateScript({[ADSI]::Exists("LDAP://$_")})] [string]$TargetOU ) try { Import-Module ActiveDirectory -ErrorAction Stop -Verbose:$false } catch { Write-Error "Active Directory module failed to Import. Terminating the script. More details : $_" exit(1) } try { #Get domain name $DomainDN = (Get-ADDomain -ErrorAction Stop).DistinguishedName #Get Computers in Domain $Computers = Get-ADComputer -Filter * -Properties PasswordLastSet -SearchBase $DomainDN -ErrorAction Stop } catch { Write-Error "Failed to query active Directory for computers. Exiting the script. More details : $_" exit(1) } $now = Get-Date $agedate = (Get-Date).AddDays(-$OlderThan) foreach($Computer in $Computers) { $ComputerName = $computer.Name Write-Verbose "Working on $ComputerName" $Computerpwdsetdate = $Computer.PasswordLastSet #Ignore if the computer is already in the given TargetOU if(([ADSI]"LDAP://$($computer.DistinguishedName)").Parent -eq "LDAP://$TargetOU") { Continue} #$Computerpwdsetdate if($Computerpwdsetdate -lt $agedate) { if($pscmdlet.ShouldProcess("$ComputerName", "Move computer account to $TargetOU")) { try { Move-ADObject -Identity $Computer.DistinguishedName -TargetPath $TargetOU -ErrorAction Stop Write-Host "Successfully Moved $ComputerName to $TargetOU" } catch { Write-Warning "Failed to move $computername to $targetOU . More details : $_" Continue } } } }
Note: I would request everyone to try this PowerShell script in your test environment before using in production.
Saved the script as written here. Then ran as such – .\Move-StaleComputers.ps1 -OlderThan 180 -TargetOU “OU=StaleComputers,DC=utm,DC=edu” -WhatIf
It resulted in this error over and over:
You cannot call a method on a null-valued expression.
At scriptpath.ps1:36 char:12
+ if($pscmdlet.ShouldProcess(“$ComputerName”, “Move computer ac …
Any idea why?
Nevermind: you have to include the
[CmdletBinding(SupportsShouldProcess=$true)]
attribute at the beginning.if I only want to move old desktop os,what I need do? Thanks
Sorry, but this script is incomplete. Fix and reupload.