SOLVED

Disable and removal of Computer accounts

Brass Contributor

Hi,

I made a script to disable old computer accounts.

My Sysadmin asked me to disable after 180 days and remove them after a year.

My goal is to disable computer accounts after 180 days and export to CSV

then delete computer accounts after 356 days and export to CSV.

 

Import-Module ActiveDirectory

# Set the Parameters since last logon
$DaysInactive = 180
$InactiveDate = (Get-Date).Adddays(-($DaysInactive))
$ForDisableLog = "C:\scripts\ComputerAccounts\Logs\For_Disable$((Get-Date).ToString('dd-MM-yyyy')).csv"

 

#-------------------------------
# FIND INACTIVE COMPUTERS
#-------------------------------

# Automated way (includes never logged on computers)
$Computers_For_Disable = Search-ADAccount -AccountInactive -DateTime $InactiveDate -ComputersOnly -SearchBase "DC=staff ,DC=local" | Where-Object {$_.distinguishedname -notlike "*,OU=Servers,*"} | Where-Object {$_.distinguishedname -notlike "*,OU=Test,*"} | Where-Object {$_.distinguishedname -notlike "*,OU=IT,*"} | Where-Object {$_.distinguishedname -notlike "*,OU=Laptops,*"} | Where-Object {$_.distinguishedname -notlike "*,CN=Computers,*"} | Select-Object Name, LastLogonDate, Enabled, DistinguishedName

#-------------------------------
# REPORTING
#-------------------------------
# Export results to CSV

$Computers_For_Disable | Export-Csv "C:\scripts\ComputerAccounts\Logs\For_Disable$((Get-Date).ToString('dd-MM-yyyy')).csv" -NoTypeInformation -Encoding UTF8

29 Replies
Do you have any question or you are just sharing the script?
Yes,
I trying to disable the computer accounts that have not been logged for 180 days, and export them on CSV file.
Also, I want to delete the computer's accounts that have not been logged for 365 days, and export them as well.

@dannytveria 

I wrote a quick script to do what you need, but please note

this script will REMOVE, and DISABLE adcomputer account, test it first and make sure its doing the result you need before applying it to production..

 

So what you need to change only is the last line, 

Get-BadPC -Days 180 -Action Disable

Days= what ever number of day

and action if you want to delete or disable.

 

function Get-BadPC{
param(
[parameter(mandatory=$true)]$Days,
[parameter(mandatory=$true)]
[ValidateSet('Delete','Disable')]$Action
)
$InactiveDate = (Get-Date).Adddays(-($Days))
$Computers_For_Action = Search-ADAccount -AccountInactive -DateTime $InactiveDate -ComputersOnly -SearchBase "DC=Test ,DC=local" | Where-Object {($_.distinguishedname -notlike "*,OU=Servers,*") -or ($_.distinguishedname -notlike "*,OU=Test,*") -or ($_.distinguishedname -notlike "*,OU=IT,*") -or ($_.distinguishedname -notlike "*,OU=Laptops,*") -or ($_.distinguishedname -notlike "*,CN=Computers,*")} 
$Computers_For_Action | Export-Csv "C:\Users\Administrator\Downloads\$($Action)-$((Get-Date).ToString('dd-MM-yyyy')).csv" -NoTypeInformation -Encoding UTF8

switch ($action){
Disable {$Computers_For_Action | Disable-ADAccount }
Delete {$Computers_For_Action | Remove-ADComputer -Confirm:$False }

}

}


Get-BadPC -Days 180 -Action Disable 
@farismalaeb
thanks for your reply. I didn`t understand, your`s script is removing and disabling the Computer account in 180 days?
No
You need only to change whats in line 20
set the number of date to whatever you want, and set the action you want to execute
so if you want to disable object which age 180 day
use the
Get-BadPC -Days 180 -Action Disable
to delete object older than 365 day use
Get-BadPC -Days 365 -Action Delete
@farismalaeb
thanks for your help, but I goal is in 1 script to do both of the processes.

@dannytveria 

If you use the script provided by @farismalaeb, you only need to add Get-BadPC -Days 365 -Action Delete on row 21 and save the file as a ps1 file.

function Get-BadPC{
param(
[parameter(mandatory=$true)]$Days,
[parameter(mandatory=$true)]
[ValidateSet('Delete','Disable')]$Action
)
$InactiveDate = (Get-Date).Adddays(-($Days))
$Computers_For_Action = Search-ADAccount -AccountInactive -DateTime $InactiveDate -ComputersOnly -SearchBase "DC=Test ,DC=local" | Where-Object {($_.distinguishedname -notlike "*,OU=Servers,*") -or ($_.distinguishedname -notlike "*,OU=Test,*") -or ($_.distinguishedname -notlike "*,OU=IT,*") -or ($_.distinguishedname -notlike "*,OU=Laptops,*") -or ($_.distinguishedname -notlike "*,CN=Computers,*")} 
$Computers_For_Action | Export-Csv "C:\Users\Administrator\Downloads\$($Action)-$((Get-Date).ToString('dd-MM-yyyy')).csv" -NoTypeInformation -Encoding UTF8

switch ($action){
Disable {$Computers_For_Action | Disable-ADAccount }
Delete {$Computers_For_Action | Remove-ADComputer -Confirm:$False }

}

}


Get-BadPC -Days 180 -Action Disable
Get-BadPC -Days 365 -Action Delete

Then you can run the script from PowerShell by just running .\ScriptLocation\scriptname.ps1

 

You could also add some logging to the script with the Write-Log Function 

function Write-Log([string[]]$Message, [string]$LogFile = $Script:LogFile, [switch]$ConsoleOutput, [ValidateSet("SUCCESS", "INFO", "WARN", "ERROR", "DEBUG")][string]$LogLevel)
{
	$Message = $Message + $Input
	If (!$LogLevel) { $LogLevel = "INFO" }
	switch ($LogLevel)
	{
		SUCCESS { $Color = "Green" }
		INFO { $Color = "White" }
		WARN { $Color = "Yellow" }
		ERROR { $Color = "Red" }
		DEBUG { $Color = "Gray" }
	}
	if ($Message -ne $null -and $Message.Length -gt 0)
	{
		$TimeStamp = [System.DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss")
		if ($LogFile -ne $null -and $LogFile -ne [System.String]::Empty)
		{
			Out-File -Append -FilePath $LogFile -InputObject "[$TimeStamp] $Message"
		}
		if ($ConsoleOutput -eq $true)
		{
			Write-Host "[$TimeStamp] [$LogLevel] :: $Message" -ForegroundColor $Color
		}
	}
}

You will have some reference for later on which devices have been disabled and which are deleted. 

@dannytveria 

The point of creating a function is to reduce code duplication, plus it provides better control of the business requirement.

 

the only change you need to do is add 1 extra line as @R_Gijsbers_Rademakers say

Get-BadPC -Days 180 -Action Disable
Get-BadPC -Days 365 -Action Delete

 

Thanks

 

Hi,
big thanks for you help guys.
but I tried on a test envoirment, and the script remove computer accounts from ou that I not wanted, like in line 21
| Where-Object {($_.distinguishedname -notlike "*,OU=Servers,*") -or ($_.distinguishedname -notlike "*,OU=Test,*") -or ($_.distinguishedname -notlike "*,OU=IT,*") -or ($_.distinguishedname -notlike "*,OU=Laptops,*") -or ($_.distinguishedname -notlike "*,CN=Computers,*")}
I found the problem the.
I saw that at the CSV file showing the computer accounts that in the OU that I didn't want to delete or disable.
There is a way that this computer account will not show in the disable or remove logs?
Simply add the OU to the exception list, so you can add extra -or condition
-or ($_.distinguishedname -notlike "*,OU=AnotherOUtoExclude,*")
I didn't understand how to do it
I don't want to see the ou that I exclude at the csv file
The Question is did the OU match any of the filter
$Computers_For_Action = Search-ADAccount -AccountInactive -DateTime $InactiveDate -ComputersOnly -SearchBase "DC=Test ,DC=local" | Where-Object {($_.distinguishedname -notlike "*,OU=Servers,*") -or ($_.distinguishedname -notlike "*,OU=Test,*") -or ($_.distinguishedname -notlike "*,OU=IT,*") -or ($_.distinguishedname -notlike "*,OU=Laptops,*") -or ($_.distinguishedname -notlike "*,CN=Computers,*")}

Try to run this line alone and then call the $Computers_For_Action variable.

I want script will check in all the domain but not in ou's that I exclude up.
Also I don't want to see the computer accounts in that ou on the csv file
Yes, the ou matches the filter -notlike.
but I don't want to see their computer accounts
function Get-BadPC{
param( 
[parameter(mandatory=$true)]$Days, 
[parameter(mandatory=$true)] 
[ValidateSet('Delete','Disable')]$Action ) 
$InactiveDate = (Get-Date).Adddays(-($Days)) 
$Computers_For_Action = Search-ADAccount -AccountInactive -DateTime $InactiveDate -ComputersOnly -SearchBase "DC=Test ,DC=local" | Where-Object {($_.distinguishedname -notlike "*,OU=Servers,*") -or ($_.distinguishedname -notlike "*,OU=Test,*") -or ($_.distinguishedname -notlike "*,OU=IT,*") -or ($_.distinguishedname -notlike "*,OU=Laptops,*") -or ($_.distinguishedname -notlike "*,CN=Computers,*")} | Select-Object Name, LastLogonDate, Enabled, DistinguishedName 
$Computers_For_Action | Export-Csv "C:\Users\Administrator\Desktop\$($Action)-$((Get-Date).ToString('dd-MM-yyyy')).csv" -NoTypeInformation -Encoding UTF8 

switch ($action){ 
Disable {$Computers_For_Action | Disable-ADAccount } 
Delete {$Computers_For_Action | Remove-ADComputer -Confirm:$False } 
} 
} 
Get-BadPC -Days 180 -Action Disable 
Get-BadPC -Days 356 -Action Delete

This is my script and i get the next error

Disable-ADAccount : The input object cannot be bound to any parameters for the command either because the command does not take pipel
ine input or the input and its properties do not match any of the parameters that take pipeline input.

@dannytveria Hi

Yes, this is expected if the number of computer object returned is zero.

You can see the result by running the query it self

$InactiveDate = (Get-Date).Adddays(-($Days))
$Computers_For_Action = Search-ADAccount -AccountInactive -DateTime $InactiveDate -ComputersOnly -SearchBase "DC=Test ,DC=local" | Where-Object {($_.distinguishedname -notlike "*,OU=Servers,*") -or ($_.distinguishedname -notlike "*,OU=Test,*") -or ($_.distinguishedname -notlike "*,OU=IT,*") -or ($_.distinguishedname -notlike "*,OU=Laptops,*") -or ($_.distinguishedname -notlike "*,CN=Computers,*")} | Select-Object Name, LastLogonDate, Enabled, DistinguishedName 

Write-Host "The Number of hosts in your search is " -NoNewline
Write-Host "$($Computers_For_Action.count)" -ForegroundColor Green
I didn`t understand why the script not working.
as I posted earlier
What is the output of the last script, are you able to get the result ?
1 best response

Accepted Solutions
best response confirmed by dannytveria (Brass Contributor)
Solution

@dannytveria 

Glad it works

Would you please mark the answer as best respones

Thanks

 

View solution in original post