Skip to main content

We are trying to remove an old local account that is on most of our windows computers.  The code removed the account when I ran it locally but not when I run it through automox.

 

# Delete a local account named "tommyboy" 
$AccountName = "tommyboy"

# Check if the account exists
if (Get-LocalUser -Name $AccountName -ErrorAction SilentlyContinue) {
# Forcefully delete the account
Remove-LocalUser -Name $AccountName -Force
Write-Host "The account '$AccountName' has been deleted successfully."
} else {
Write-Host "The account '$AccountName' does not exist."
}

 

Hi Slammert,

This is a situation where get-localuser is not available for 32-bit powershell

 

 

I was able to get this pieced together which worked, using 32-bit available commands:

 

# ======================
# Otto AI Generated Code
# ======================
# Define the username of the account you want to delete
$username = "delete-me" # Replace with the actual username

# Check if the user exists using net user command
$userExists = net user | Select-String -Pattern $username

if ($userExists) {
# Remove the user account using net user command
net user $username /delete
Write-Host "User account '$username' has been deleted."
} else {
Write-Host "User account '$username' does not exist."
}

 


Thanks Mark!!!

 


<#  Local User Removal
Flow:
1) If logged in, try up to 3 times to force logoff; stop on first success
2) Disable (optional)
3) Delete account (optional)
4) Delete profile by SID (optional)
Exit: 0 ok/done, 1 error
#>

# ------------ User Variables ------------
$RemoveUsername = @('Firstname Surname')
$ProtectedNames = @('Administrator','svc_','WDAGUtilityAccount','svc_VeeamBackup')

$DisableAccount = $true # disable after sign-off
$DeleteAccount = $true # delete the account
$DeleteProfile = $true # delete Windows profile

$LogoffTries = 3 # attempts to force logoff
$BetweenTriesSec = 2 # seconds between attempts
# -----------------------------------------------------

function Get-UserSessionIds {
param([string]$User)
$raw = quser "$User" 2>$null
if (-not $raw) { return @() }
($raw -split "`n" | Select-Object -Skip 1 | ForEach-Object {
$m = [regex]::Match($_, '\s+(\d+)\s+\S+\s')
if ($m.Success) { [int]$m.Groups[1].Value }
}) | Where-Object { $_ -ne $null }
}

try {
if ($ProtectedNames -contains $RemoveUsername) { throw "Avoiding operation on protected account '$RemoveUsername'." }

$user = Get-LocalUser -Name $RemoveUsername -ErrorAction SilentlyContinue
if (-not $user) { Write-Output "User '$RemoveUsername' not found. Nothing to do."; exit 0 }

# Capture SID once (profile deletion can occur after account deletion)
$sid = $user.SID.Value

# 1) If logged in, try up to N times to force logoff; stop on first success
$sessions = Get-UserSessionIds -User $RemoveUsername
for ($i = 1; $i -le $LogoffTries -and $sessions.Count -gt 0; $i++) {
foreach ($sidSession in $sessions) { try { logoff $sidSession 2>$null } catch {} }
Start-Sleep -Seconds $BetweenTriesSec
$sessions = Get-UserSessionIds -User $RemoveUsername
if ($sessions.Count -eq 0) { break }
}

# 2) Disable (optional)
if ($DisableAccount -and $user.Enabled) {
Disable-LocalUser -Name $RemoveUsername -ErrorAction Stop
Write-Output "Disabled '$RemoveUsername'."
}

# 3) Delete account (optional)
if ($DeleteAccount) {
Remove-LocalUser -Name $RemoveUsername -ErrorAction Stop
Write-Output "Deleted account '$RemoveUsername'."
}

# 4) Delete profile (optional)
if ($DeleteProfile -and $sid) {
$prof = Get-CimInstance Win32_UserProfile -Filter "SID='$sid'" -ErrorAction SilentlyContinue
if ($prof) {
Remove-CimInstance $prof -ErrorAction SilentlyContinue
Write-Output "Deleted profile for SID $sid."
}
}

exit 0
}
catch {
Write-Output "ERROR: $($_.Exception.Message)"
exit 1
}


Looks good, a few improvements that I’d suggest:
 

  • check if a user is logged on
  • if logged on, include a timer or force logoff with 3 or more tries with verification between each step
  • an exclusion filter ensuring certain accounts do not get removed; such as administrative service accounts

Building safety into the script ensures more flexibility in the long-term; without breaking any existing processes or workflows. And, this does not need a scheduled task.

Possible future considerations: 

  • add function to measure how long script to run
  • add timestamp for each step with verbose logging
  • add simple loop to deleting user accounts
  • add simple loop to remove user profile
  • add a singular loop instead of having many (more code to maintain)
  • return the username with SID once queried before any removal
  • account lockout considerations
  • force password reset
  • remove users from local group

Reply