Forum Discussion
User Profile Deletion
You can try this in detection and check if it detects correctly the profiles.
$cutoff = (Get-Date).AddMinutes(-60)
Write-Output "`n---- Profile Diagnostic Report ----"
Write-Output "Cutoff time: $cutoff"
# Get tasklist output once
$tasklistOutput = tasklist /v
Get-ChildItem "C:\Users" -Directory -ErrorAction SilentlyContinue |
ForEach-Object {
$folder = $_
$folderPath = $folder.FullName
$ntName = $folder.Name
$lastWrite = $folder.LastWriteTime
$idleMinutes = [math]::Round(((Get-Date) - $lastWrite).TotalMinutes)
$profile = Get-CimInstance -Class Win32_UserProfile -ErrorAction SilentlyContinue |
Where-Object { $_.LocalPath -eq $folderPath }
$status = "Unknown"
$isSpecial = $false
$canBeDeleted = $false
if ($profile) {
$isSpecial = $profile.Special
if (-not $profile.Loaded) {
$status = "Unloaded"
if (-not $isSpecial -and
$ntName -notlike "*Windows*" -and
$ntName -notlike "*default*" -and
$ntName -notlike "*Public*" -and
$ntName -notlike "*Admin*" -and
$lastWrite -lt $cutoff) {
$canBeDeleted = $true
}
} else {
# Loaded profile — check process activity
$tasklistName = "$env:COMPUTERNAME\$ntName"
$hasProcess = $tasklistOutput | Where-Object {
$_ -match "\b$([regex]::Escape($tasklistName))\b"
}
$status = $hasProcess ? "Loaded Active" : "Loaded Idle"
}
}
[PSCustomObject]@{
FolderName = $ntName
LastWriteTime = $lastWrite
IdleMinutes = $idleMinutes
Status = $status
IsSpecial = $isSpecial
Deletable = $canBeDeleted
ProfileFound = [bool]$profile
}
} | Sort-Object LastWriteTime | Format-Table -AutoSize
- ddickinsonBHCETMay 22, 2025Copper Contributor
Hey, Luca_Scarano_TheItalianWay
Thanks for your reply. I will get round to testing this.
Could you kindly explain what you have changed and why you think it would make a difference when deleting profiles on older enrolled devices. This is also a learning process for me, so would be glad to take any advice or methodology on board.
- May 22, 2025
Hi,
use it just as a diagnostic. Profiles can result loaded also if they are not, and folders can be accessed also by background process, giving you false information on last activity.
I would better go with a simple task list.
In this case I kept Deletable false for loaded idle profiles (without processes). From this script you can already understand if this kind of detection works better for you, and after fix in the general script.