Programmatically delete a user’s profile

Deleting old and orphaned user profiles on a PC can easily be done using the Advanced System Properties dialog.

But is there a way to delete local Profiles remotely? In short: Yes, there is.

And even better, you can do this all from command line or from Powershell. The WMI class Win32_UserProfile offers a not very well documented Delete method, which allows to delete user profiles remotely. This method can be executed in CMD Command Prompts (WMIC), Powershell (Invoke-WmiMethod) or compiled applications. Note that it only deletes the specified user’s profile and not the user account itself.

Before you can delete a profile remotely, make sure that the user executing the Delete method has administrative rights on the target computer. Also make sure that the Windows Remote Management service (WinRM) is running on the target computer and no firewall rules are defined to block remote management requests. The Powershell command Enable-PSRemoting takes care of all the necessary settings.

Let’s assume you need to delete the profile of the user HSolo on the computer Bespin. In a powershell window type:

(Get-WmiObject -Class Win32_UserProfile -Computername Bespin | Where {$_.localpath -eq "C:\Users\HSolo"}).Delete()

Here’s another example using a command prompt, if you do not want to use powershell for some reason:

WMIC /node:"Bespin" Path Win32_UserProfile Where "LocalPath Like 'C:\\Users\\HSolo'" Delete

Both commands do not distinguish between local users and domain users. If Roaming Profiles are used, only the local copy of the profile gets deleted. The profile stored on the server is left alone. Note that you can’t delete a profile of a logged on user. It’s recommended to check if a user is logged on before trying to delete the profile. This can be done easily by checking the owner of the process Explorer.exe.

The following script takes care of this. You can save it as .PS1 or use it as a reference.

param
(
	[switch] $List = $false,

    [string] $Computer = $env:COMPUTERNAME,
    
    [string] $ProfileRoot = "C:\Users",

	[string] $User
)

$scriptRoot = (Get-Item $MyInvocation.MyCommand.Definition).DirectoryName
$scriptBaseName = (Get-Item $MyInvocation.MyCommand.Definition).BaseName
$desktopPath = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders").GetValue("Desktop")

$explorerOwner = (Get-WmiObject Win32_Process -ComputerName $Computer -Filter "Name = 'Explorer.exe'" | Invoke-WmiMethod -Name GetOwner).User
$profileList = Get-WmiObject -Class Win32_UserProfile -ComputerName $Computer
foreach ($userProfile in $profileList)
{
    $localUser = $userProfile.LocalPath.Substring($userProfile.LocalPath.LastIndexOf("\") + 1)
    if ($localUser -eq $explorerOwner)
    {
        if ($List)
        {
            Write-Host "$localUser (Currently logged on, cannot be deleted)"
        }
        if ((!$List) -and ($localUser -eq $user))
        {
            Write-Host "$localUser is currently logged on. Log off user and retry."
        }
    }
    elseif ($userProfile.LocalPath.IndexOf($ProfileRoot, [System.StringComparison]::CurrentCultureIgnoreCase) -eq -1)
    {
        if ($List)
        {
            Write-Host "$localUser (System, cannot be deleted)"
        }
        if ((!$List) -and ($localUser -eq $user))
        {
            Write-Host "$localUser is a system account, which profile cannot be deleted."
        }
    }
    else
    {
        if ($List)
        {
            Write-Host $localUser
        }
        if ((!$List) -and ($localUser -eq $user))
        {
            Write-Host "Found match. Deleting profile of $localUser."
            $userProfile.Delete()
        }
    }
}

Posted

in

by

Tags:

Comments

Leave a Reply