Automatic bulk removal of Terminal Server user profiles

Automatic bulk removal of Terminal Server user profiles

Use the following script to automatically remove unused terminal server user profiles (V2 -> V6) from your profiles folder to keep the system clean.

Simply add it to a Windows scheduled task to let it run every now and then and the script does the rest. For easy follow-up the script provides basic output of what it’s doing and what the final status was. You can include a start-transcript to the code to log the output on every run.

This script helped me clean up over 100 unused TS profiles on one of our servers and reclaim a lot of diskspace 🙂

cls

Import-Module ActiveDirectory

$profileDirectory = "\\MyProfileServer\Profiles"
$allProfiles = Get-ChildItem -Path $profileDirectory -Directory

$counterAll = $allProfiles.Count
$counterNE = 0
$counterDE = 0
$counterOldAccount = 0
$counterRecentlyUsed = 0

# Days to keep account
$days = 365

# Take ownership and delete user if they do NOT exist or older then $days (stale)
Function RemoveAccount
{
param([string] $profilePath)

# Take ownership and delete user if they do NOT exist
try
{
###
# Take ownership before removal

# Needed to chown the files and files
takeown /f "$profilePath" /r /d y

# grants ownerships to your admin account with /t
icacls $profilePath /q /c /t /reset

#Write-Host ""
Write-Host "Claimed ownership"

###
# Remove folder and contents
try
{
Remove-Item -LiteralPath $profilePath -Force -Recurse

Write-Host ""
Write-Host "Deleted folder"
}
catch
{
Write-Host ""
Write-Host "Could not delete folder"
}
}

# Catch any errors for further troubleshooting
catch
{
Write-Host ""
Write-Host "Error occured on $profilePath"
}
}

foreach($profile in $allProfiles)
{
###
# Explanation of Windows Roaming Profile versions
# V2 = Windows 7 | Windows Server 2008 R2
# V3 = Windows 8.0 - 8.1 | Windows Server 2012 - 2012 R2
# V4 = Windows 8.1 | Windows Server 2012 R2
# V5 = Windows 10 (1507 to 1511) | Windows Server 2016
# V6 = Windows 10 (1607 and later) | Windows Server 2016 and later
$updatedProfileName = $profile.BaseName -replace ".v2","" -replace ".v3","" -replace ".v4","" -replace ".v5","" -replace ".v6",""

# Check if the user's acronym exists or not
try
{
$foundUser = Get-ADUser -Identity $updatedProfileName -Server deuproact001
$UserExists = $true

$counterDE++

Write-Host ""
Write-Host "User $updatedProfileName exists."
}
catch [Microsoft.ActiveDirectory.Management.ADIdentityResolutionException]
{
$UserExists = $false

$counterNE++

Write-Host ""
Write-Host "User does $updatedProfileName not exist."
}

# If the user does not exist then we can remove the profile
if($UserExists -eq $False)
{
# Call to RemoveAccount function
RemoveAccount -profilePath $profile.FullName
}

# If the user exists then check the staleness of the profile
elseif($UserExists -eq $True)
{
Write-Host ""
Write-Host "Checking age of profile $profile"

# If the account is older then $days remove it
if ($profile.LastWriteTime -le (Get-Date).AddDays(-$days))
{
$counterOldAccount++

Write-Host "Older then 1 year, deleting profile"
Write-Host "Last write time = " $profile.LastWriteTime

RemoveAccount -profilePath $profile.FullName
}

# Else keep the account
else
{
$counterRecentlyUsed++

Write-Host "Recently used, keep profile"
Write-Host "Last write time = " $profile.LastWriteTime
}
}

Write-Host "###"
}

Write-Host ""
Write-Host "###"
Write-Host "User(s) $counterNE of $counterAll users do not exist"
Write-Host "User(s) $counterDE of $counterAll users still exist"
Write-Host "###"
Write-Host "Profiles not used in over $days days = $counterOldAccount"
Write-Host "Profiles used recently = $counterRecentlyUsed"
Write-Host "###"

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *