Skip to content

[Powershell] Corrupt Userprofiles – Quick fix via Powershell

Customer X had a long ongoing problem with userprofiles getting corrupted due to their antivirus solution holding the ntuser.dat file hostage. It took a while before we found the cause of this problem so we had to think of a quick fix to keep things running.
Another problem was that the locally stored corrupted profile was getting synced to the profile server, causing trouble for users on multiple workstations.

To save time and to give the sysadmins an easy way to clean these corrupted profiles, I automated the process with this (admittedly messy) script.

I’ve also added some workarounds that start the required services used in this script, because in some cases these are not enabled (WinRM, Remote Registry, etc.)

Note: The text in the popup is in Dutch.

<#
.Description
   Script for cleaning up corrupted userprofiles.
   Gebaseerd op: 	https://technet.microsoft.com/en-us/library/ff730941.aspx
					https://msexchange.me/2014/03/11/powershell-custom-gui-input-box-for-passing-values-to-variables/

   Current Version: 1.2
   Versiebeheer:
   ----------------
   v1.0: First working version
   v1.1: Added automated starting of the required services
   v1.2: Script cleaned up
   
   Door: Stefan van Bruggen, de Koning B.V.
		 [email protected]

#>

function button ($title,$username,$workstation) {

## Laden van assemblys
[void][System.Reflection.Assembly]::LoadWithPartialName( “System.Windows.Forms”)
[void][System.Reflection.Assembly]::LoadWithPartialName( “Microsoft.VisualBasic”)

## Formaat van het input-venster
$form = New-Object “System.Windows.Forms.Form”;
$form.Width = 500;
$form.Height = 200;
$form.Text = $title;
$form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen;

## Definieren van label1
$textLabel1 = New-Object “System.Windows.Forms.Label”;
$textLabel1.Left = 25;
$textLabel1.Top = 15;
$textLabel1.Text = $username;

## Definieren van label2
$textLabel2 = New-Object “System.Windows.Forms.Label”;
$textLabel2.Left = 25;
$textLabel2.Top = 50;
$textLabel2.Text = $workstation;


## Definieren van input-veld box1
$textBox1 = New-Object “System.Windows.Forms.TextBox”;
$textBox1.Left = 150;
$textBox1.Top = 10;
$textBox1.width = 200;

## Definieren van input-veld box2
$textBox2 = New-Object “System.Windows.Forms.TextBox”;
$textBox2.Left = 150;
$textBox2.Top = 50;
$textBox2.width = 200;

## Definieren van standaardwaarde input-velden
$textBox1.Text = "Gebruikersnaam";
$textBox2.Text = "Werkstation";

## Definieren van OK-knop
$button = New-Object “System.Windows.Forms.Button”;
$button.Left = 360;
$button.Top = 85;
$button.Width = 100;
$button.Text = “Ok”;

## Definieren van actie bij klikken OK
$eventHandler = [System.EventHandler]{
$textBox1.Text;
$textBox2.Text;
$form.Close();};
$button.Add_Click($eventHandler) ;

## Definieren van controls
$form.Controls.Add($button);
$form.Controls.Add($textLabel1);
$form.Controls.Add($textLabel2);
$form.Controls.Add($textBox1);
$form.Controls.Add($textBox2);
$ret = $form.ShowDialog();

## Definieren van ingevoerde waarden

return $textBox1.Text, $textBox2.Text
}

$return= button “Invoer Gebruikersgegevens” “Gebruikersnaam” “Computernaam”

## De waarden die zijn ingevoerd zijn op te vragen via
## $return[0] voor de username
## $return[1] voor het werkstation

## Define profile share
$ProfileShare = "\\SERVER01.domain.local\Profiles$\"

## Define full path to userprofile
$FullPath = $ProfileShare + $return[0] + ".v2" 

## Rename ntuser.dat on the profile server
Get-ChildItem $FullPath -recurse -force | Where {$_.name -eq "ntuser.dat"} | rename-item -newname {  $_.name  -replace "ntuser.dat","ntuser.dat_old"  }

## Get the SID for the deletion of the registry key
$usersidrequest = $return[0]
$userSID = ([System.Security.Principal.NTAccount]("ahoy.local\$usersidrequest")).Translate([System.Security.Principal.SecurityIdentifier]).Value

## Delete registry key on the werkstation and starting of Remote Registry service
$workstation = $return[1]
(Get-Service -ComputerName $workstation -Name "WinRM").Start()
(Get-Service -ComputerName $workstation -Name "RemoteRegistry").Start()

$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(‘LocalMachine’,$workstation)

       $regKey= $reg.OpenSubKey(“SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList”,$true )
       $regKey.DeleteSubKeyTree($userSID)

## Rename locally cached userprofile to _old
$workstationunc = "\\" + $workstation + "\c$\Users\"
$workstationuser = $return[0]
$rename = $workstationuser + "_old"
Get-ChildItem $workstationunc -force | Where {$_.name -eq $workstationuser} | rename-item -newname {  $_.name  -replace $workstationuser,$rename } -ErrorAction Continue

 

 

Published inPowershell
Stefan van Bruggen - 2019