Deleting a local account sounds like one task, but it will at least consist of the following three steps:
- Delete the account from the local account database
- Delete the profile directory of this account
- Delete the account profile from the registry
There might be even more steps, but I have not found any documentaion on them so far. As there are several steps to perform, it is probably a bad idea to use too atomic functions for that. The Remove-LocalUser
cmdlet and the net
tool (with net user <username> /delete
) are such atomic functions. They suggest to delete a local user - which sounds good - but they actually (only) delete the user from the local user account database. This might be sufficient for some scenarios, but be aware that registry keys and the profile directory will remain!
Microsoft offers a macro function to completely delete a local user account, unfortunately only in the GUI. You can find it through Settings > Accounts > Family & other users. Just select a user and click on Remove, then on Delete account and data. This will perform all three steps from above.
There is also a macro function to (just) remove the profile of a user. You can open it via Control Panel > System > Advanced system settings > Settings... (button in the User Profiles panel):
You can also open this window directly by executing rundll32 sysdm.cpl,EditUserProfiles
in an elevated PowerShell. It is important to open this window with administrative privileges to see all user accounts and not only the own account (even when opening via GUI).
Deleting a user account through this window will perform steps 2 and 3 from above.
Wondering what the two unknown accounts are? They are the remains of two deleted accounts, one deleted by the Remove-LocalUser
cmdlet and one by the net
tool.
As you are looking for a PowerShell solution, we can at least perform the three steps from above manually, as long PowerShell does not provide a cmdlet to do all the work at once:
function Remove-LocalUserCompletely {
Param(
[Parameter(ValueFromPipelineByPropertyName)]
$Name
)
process {
$user = Get-LocalUser -Name $Name -ErrorAction Stop
# Remove the user from the account database
Remove-LocalUser -SID $user.SID
# Remove the profile of the user (both, profile directory and profile in the registry)
Get-CimInstance -Class Win32_UserProfile | ? SID -eq $user.SID | Remove-CimInstance
}
}
# Example usage:
Remove-LocalUserCompletely -Name 'myuser'
This function is ready to be used in a pipeline, so you could delete all users except the ones you want to keep like this:
Get-LocalUser | ? Name -NotIn Administrator, DefaultAccount, DevToolsUser, Guest, sshd, User, WDAGUtilityAccount | Remove-LocalUserCompletely
But currently (in PS v5.1.18362.752) the pipeline between Get-LocalUser
and Remove-LocalUser
is bugged, which will also affect my function above. The following pipeline (without Remove-LocalUserCompletely
) will only remove every second user account from the account database of the accounts that should be deleted:
Get-LocalUser | ? Name -NotIn Administrator, DefaultAccount, DevToolsUser, Guest, sshd, User, WDAGUtilityAccount | Remove-LocalUser
You can work around this by using a loop instead of a pipeline (now with Remove-LocalUserCompletely
):
$users = Get-LocalUser | ? Name -NotIn Administrator, DefaultAccount, DevToolsUser, Guest, sshd, User, WDAGUtilityAccount
foreach ($user in $users) {
Remove-LocalUserCompletely -Name $user.Name
}