Thanks Mark,
Ignore list created in script and working but I am getting an error when I try to delete a user from the list
error: "INFO: C:\Users\C:\Users\user3 Profile does not exist on server-1"
"INFO: C:\Users\C:\Users\user3 Profile does not exist on server-2"
I can see the user profile exists on the servers
Briefly,
I have several Citrix servers (although I have a script that runs every night to clear orphaned profiles), now and again I get corrupted profiles during the day, this script is to allow me delete a single user from multiple servers. I like the GUI because it lets me select a single user and delete from all servers listed in the script.
My script:
#GUI interface to delete user profiles from remote desktop session host server
#Setup script variables
#add computers to computers variable to search for profiles on those computers
[array] $Computers = "server1","server2"
$log = "\\server5\c$\logs\logs.txt"
$date = Get-Date
#Reset variables
$selecteduser = ""
$profilelist = @()
Function SetupForm {
#Setup the form
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = "Select user(s)"
$objForm.Size = New-Object System.Drawing.Size(300,320)
$objForm.StartPosition = "CenterScreen"
$btnDelete = New-Object System.Windows.Forms.Button
$btnDelete.Location = New-Object System.Drawing.Size(120,240)
$btnDelete.Size = New-Object System.Drawing.Size(75,23)
$btnDelete.Text = "Delete Profile"
$objForm.Controls.Add($btnDelete)
#When a user clicks the log off button get the details of the logged in users and call the scriptactions function
$btnDelete.Add_Click(
{
#set the selecteduser variable to be that of the user selected in the form
$selecteduser = $objCombo.SelectedItem
DeleteProfile
#$objForm.Close()
})
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(200,240)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = "Please select user to delete profile:"
$objForm.Controls.Add($objLabel)
$objCombo = New-Object System.Windows.Forms.ComboBox
$objCombo.Location = New-Object System.Drawing.Size(10,40)
$objCombo.Size = New-Object System.Drawing.Size(260,20)
$objCombo.Height = 80
#Run through each computer in the computers variable to compile a list of unique user accounts across all servers
ForEach ($computer in $Computers) {
#use WMI to find all users with a profile on the servers
Try{
$ignoreList = @{
"C:\Users\mmaclach" = "1"
"C:\Users\Administrator" = "1"
"C:\Users\Ctx_StreamingSvc" = "1"
"C:\Users\Default" = "1"
"C:\Users\CitrixSQLsvc" = "1"
"C:\Users\Public" = "1"
}
[array]$users = Get-WmiObject -ComputerName $computer Win32_UserProfile -filter "LocalPath Like 'C:\\Users\\%'" | Select LocalPath -ea stop
ForEach($userProfile in $users){
if (-Not ($ignoreList.ContainsKey($userprofile.LocalPath)))
{
[void] $objCombo.Items.Add($userprofile.LocalPath)
}
}
$objForm.Controls.Add($objCombo)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
}
Catch {
Write-Warning "$($error[0]) "
Break
}
#compile the profile list and remove the path prefix leaving just the usernames
$profilelist = $profilelist + $users.localpath -replace "C:\\users\\"
#filter the user names to show only unique values left to prevent duplicates from profile existing on multiple computers
$uniqueusers = $profilelist | Select-Object -Unique
}
#adds the unique users to the combo box
ForEach($user in $uniqueusers) {
[void] $objCombo.Items.Add($user)
}
$objForm.Controls.Add($objCombo)
$objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
}
Function DeleteProfile {
#Add the path prefix back to the selected user
$selectedUser = "C:\Users\$selecteduser"
#This section reads through all the computers and deletes the profile from all the computers - it catches any errors.
ForEach ($computer in $Computers) {
Try {
(Get-WmiObject -ComputerName $computer Win32_UserProfile | Where {$_.LocalPath -eq $selecteduser}).Delete()
Write-Host -ForegroundColor Green "$selecteduser has been deleted from $computer"
Add-Content $log "$date $selecteduser profile has been deleted from $computer"
}
Catch [System.Management.Automation.MethodInvocationException]{
Write-Host -ForegroundColor Red "ERROR: Profile is currently locked on $computer - please use log off user script first"
Add-Content $log "$date $selecteduser Profile is currently locked on $computer - please use log off user script first"
}
Catch [System.Management.Automation.RuntimeException] {
Write-Host -ForegroundColor Yellow "INFO: $selecteduser Profile does not exist on $computer"
Add-Content $log "$date INFO: $selecteduser Profile does not exist on $computer"
}
Catch {
Write-Host -ForegroundColor Red "ERROR: an unknown error occoured. The error response was $error[0]"
Add-Content $log "$date ERROR: an unknown error occoured. The error response was $error[0]"
}
}
#Add a label to say process is complete
$objLabel1 = New-Object System.Windows.Forms.Label
$objLabel1.Location = New-Object System.Drawing.Size(10,100)
$objLabel1.Size = New-Object System.Drawing.Size(280,20)
$objLabel1.Text = "Deletion complete, check log for more details."
$objForm.Controls.Add($objLabel1)
#Add a view log button to view the log file
$LogButton = New-Object System.Windows.Forms.Button
$LogButton.Location = New-Object System.Drawing.Size(50,150)
$LogButton.Size = New-Object System.Drawing.Size(75,23)
$LogButton.Text = "View Log"
$LogButton.Add_Click({Invoke-Item $log})
$objForm.Controls.Add($LogButton)
}
#Check script was run as admin
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
[System.Windows.Forms.MessageBox]::Show("It doesn't appear you have run this PowerShell session with administrative rights, the script may not function correctly. If no users are displayed please ensure you run the script again using administrive rights.")
}
#Start the form
SetupForm