PowerShell Profile Removal GUI

In a previous article, I showed you how you can use PowerShell to remove local profiles from local and remote systems. A couple of downsides to using this was:

  1. This only worked on Vista and above Operating Systems
  2. You can only remove one profile at a time (this was mitigated Peter in the comments section)
  3. This is all done through the PowerShell console, no GUI to work with

After some work and a few delays, I have finally finished (for the most part) my update to my other profile removal script that includes support for XP and 2003 systems, allows for the removal of more than one system and also is a GUI!

Run the ProfileRemovalGUI.ps1 file to bring up the GUI as shown below.

image

 

It is recommended that you are running this as an Administrator also. Once the UI is up and running, simply type in a hostname and click connect.

I have tried to make this a pretty robust utility for locating and removing profiles. One thing I included is the ability to locate Temp. profiles that occasionally popup for one reason or another.

I was able to make this work for XP and 2003 systems where the Win32_UserProfile class doesn’t exist by performing a registry query for HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList and enumerate through each SID folder and from there I can get the location of the profile folder via the ProfileImagePath key. To be sure that I cleanly remove the profile data from the system, I remove both the profile folder and the registry key. Code snippet below for the query:

    $basekey = "LocalMachine"
    $registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($basekey,$Server)
    $SubKey = $registry.OpenSubKey("Software\Microsoft\Windows NT\CurrentVersion\ProfileList",$True)
    $Exclusions = "systemprofile","LocalService","NetworkService"  
    $Registrydata = ForEach ($key in $Subkey.GetSubKeyNames()) {
        $RegProfile = $registry.OpenSubKey("Software\Microsoft\Windows NT\CurrentVersion\ProfileList\$key",$True)
        $LocalPath = ($RegProfile.GetValue("ProfileImagePath") -replace "C:\\","\\$($Server)\C$\")
        $UserName = Split-Path $LocalPath -Leaf
        $regpath = ($RegProfile.name -replace "HKEY_LOCAL_MACHINE\\","")
        If ($Exclusions -notcontains $UserName) {
            New-Object PSObject -Property @{
                Username = $UserName
                LocalPath = $LocalPath
                SID = $key
                IsActive = "NA"
                RegistryPath = $regpath
                Type = 'Registry'
            }
        }
    

 

For the rest of the systems (Vista and above) I use the Win32_UserProfile WMI class to perform the queries and I then use Remove-WMIObject to remove the WMI path to each selected profile.

Lets make a connection to my Vista laptop to see what profiles I want to remove:

image

Here you see the username, sid, localpath to the profile folder and whether the profile is currently in use (IsActive) in which it cannot be removed. Note that the IsActive is only applicable to Vista and higher Operating Systems.

Lets remove the TestUser profile since I do not need it on my laptop.

image

As you can see, the TestUser profile has been removed now only laptop and the UI has been refreshed to show that only my profile (Boe) remains (Note: the Profile Count: has been updated since this screenshot and is now displaying properly).

Now on to a Windows 2003 Server to show the backwards compatibility of this utility:

image

Again, like the query for Vista and above operating systems, you get the same information with the exception of the IsActive column that only shows NA due to not being able to tell if the profile is currently in use.

The same process remains though to remove one or more profiles. Simply select as many profiles that you wish to remove and click Remove Profiles.

image

image

As you can see, profiles have been removed. The profiles have been removed both at the file/folder level and at the registry level.

Give it a shot and let me know what you think!

Updated: 9 Oct 2011 —
        Version: 1.2
            -> Added LastAccess column to UI
            -> Added autorefresh of list view after removal of profiles
            -> Added cancel button
            -> Fixed bug where some profile folders were not being included in registry or wmi queries but folders existed

Download

ProfileRemovalGUI.ps1

This entry was posted in powershell, scripts and tagged , , . Bookmark the permalink.

11 Responses to PowerShell Profile Removal GUI

  1. Joey says:

    Specifically “How can i output the profile name of the Selected Items being removed to Text file?

  2. Mitch (@WRX_Mitch says:

    I know it’s been a while since this was released but is anyone else having performance issues? I type in the PC name, click connect and it just sits there indefinitely saying “Retrieving list of profiles from…”
    If I click the Cancel button, it will stop querying and populate the profiles in the below window and show the correct count.
    Same holds true if I select a profile or two to delete and click the “Remove Profiles” button… It just sits there and never finishes on its own…
    Have tried this from my Win7 SP1 desktop as well as our Server 2008R2 RDP server both with PSv3.

  3. Dave Hahn says:

    Now if I could go to network roaming profiles to delete……
    Thanks much for this.

  4. Gilbert says:

    Hi Boe, this is a wonderful script, but I had to adjust it a little to make it work in our environment.
    Some of our servers do not have ‘C’ as the SystemDrive, so the hardcoded references to the C-drive don’t always work well.
    In both Pre- and PostVistaLocalProfile I’ve added a query for the local system drive of the remote computer. The result can then be used for setting the profile locations.
    Pre: $RemoteSystemDrive = (($registry.OpenSubKey(“Software\Microsoft\Windows NT\CurrentVersion”,$True)).GetValue(“SystemRoot”))[0]
    Post: $RemoteSystemDrive = (Get-WmiObject -ComputerName $server -Class Win32_OperatingSystem | Select-Object -ExpandProperty SystemDrive)[0]

  5. Joe_P says:

    I want to add an additional folder to delete based on the user’s SID. The script kees exiting though when I add the line to the postvistadelete section.

    I am trying to delete \\$server\c$\appsensevirtual\$SID
    is that the right spot and format?

  6. For the XP IsActive property, you can find the active profiles via the process list:

    Get-WmiObject Win32_Process | Select @{n=”User”;e={$_.GetOwner().User}} -Unique

    • Boe Prox says:

      This was something that I was looking at, but I ended up getting sidetracked on something else and never got around to using this method. I also wanted to make sure that it will accurately reflect the proper profile in the case of .xxxx profiles that occur.
      Something that I should revisit sometime soon…

      • You can try enumerating through the HKU registry hive to see which user hives are loaded and then query the user profile path to get the active (profile).xxxx profiles.

        • Boe Prox says:

          I was actually looking at that hive for a different reason in the beginning. I think I like that approach a little more anyways to get the IsActive property than using the Win32_Process with GetOwner() just based on performance. Looks like something I will check out in greater detail tomorrow. I also need to get the semantics right on grabbing the correct profile folder that is active. I’ve seen up to 4 or 5 stacked profile folders: username.domain, username.domain000, username.domain001, etc… Got an idea in mind that might work, so we will see.

  7. Fantastic! Have you thought about displaying last modified date on the profile directory? Perhaps as a means to identify profiles that haven’t been used in a while?

Leave a comment