Trouble Deleting user profile

by cmore86 at 2012-08-31 11:18:27

I have the following script.

It goes into the server remotely and looks for profiles that are disabled and does not exist.

This goes through the profiles and deletes the profile along with the directory under c:/users in order to free up space.

The issue I am running into is trying to get this to delete profile that is noted as "disabled" or "null or not existent".

The code is as follows:

$computer = "cg-ts-4"
[array]$users = Get-WmiObject -ComputerName $computer Win32_UserProfile -filter "LocalPath Like ‘C:\Users\%’" -ea stop
$num_users = $users.count
Write-Host -ForegroundColor Green "User profiles on $($computer):"
For ($i=0;$i -lt $num_users; $i++)
{ $username = "$(($users[$i].localpath).replace(‘C:\Users',’‘))"
$userdelete = $users
$searcher = new-object DirectoryServices.DirectorySearcher([ADSI]“”)
$searcher.filter = “(&(objectClass=user)(sAMAccountName= $username))”
$founduser = $searcher.findOne()
$user = $founduser.Properties.useraccountcontrol


if ($user -eq 514)
{
Write-Output "$username - Will be Destroyed."
(gwmi win32_Userprofile | where {$.LocalPath -like "c:\users\test"}).delete()
}
elseif ($user -eq 512)
{
# Write-Output "$username - You live another day."
}
elseif ($user -eq $null)
{
Write-Output "$username - Account does not exist."
}}


I have tried using remove-item and a (variable).delete method and neither seems to work. As it either gives me these errors:

You cannot call a method on a null-valued expression.
At C:\DUFS3.ps1:17 char:80
+ (gwmi win32_Userprofile | where {$
.LocalPath -like "c:\users\test"}).delete <<<< ()
+ CategoryInfo : InvalidOperation: (delete:String) , RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull

I also get this error when trying the Remove-Item cmdlet:


Remove-Item : Illegal characters in path.
At C:\DUFS3.ps1:26 char:15
+ Remove-Item <<<< $userdelete
+ CategoryInfo : InvalidArgument: (\CG-TS-4\root.…3354035451-500":String) [Remove-Item], ArgumentException
+ FullyQualifiedErrorId : ItemExistsArgumentError,Microsoft.PowerShell.Commands.RemoveItemCommand

Remove-Item : Cannot find path ‘\CG-TS-4\root\cimv2:Win32_UserProfile.SID="S-1-5-21-325964096-1960298684-3354035451-500"’ because it does not exist.
At C:\DUFS3.ps1:26 char:15
+ Remove-Item <<<< $userdelete
+ CategoryInfo : ObjectNotFound: (\CG-TS-4\root.…3354035451-500":String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand

The error is a lot longer than this.

I have been banging my head against my desk trying to figure this out and have found no luck with Google, so decided to try here.

Any and all assistance will be greatly appreciated.
by DonJ at 2012-08-31 11:24:23
So, the first error, which you’re getting with the Delete() method, is indicating that the Get-WmiObject command isn’t returning any objects. What happens if you just run:


gwmi win32_Userprofile | where {$.LocalPath -like "c:\users\test"}


by itself? I suspect the other errors are related to the same root cause. I guess one thing I’m confused about is "deleting profiles that don’t exist…" if they don’t exist, what is it you’re deleting?
by cmore86 at 2012-08-31 11:39:36
I will try that. The original code. Is able to delete the profile whether it exists or not. This code is combining two features, one of them being to make sure the user is enable or not, and if no longer in the directory.

The original code is as follows:

<#
.SYNOPSIS
Interactive menu that allows a user to connect to a local or remote computer and remove a local profile.
.DESCRIPTION
Presents an interactive menu for user to first make a connection to a remote or local machine. After making connection to the machine,
the user is presented with all of the local profiles and then is asked to make a selection of which profile to delete. This is only valid
on Windows Vista OS and above for clients and Windows 2008 and above for server OS.
.NOTES
Name: Remove-LocalProfile
Author: Boe Prox
DateCreated: 26JAN2011
.LINK
http://boeprox.wordpress.com
http://msdn.microsoft.com/en-us/library/ee886409%28v=vs.85%29.aspx
.EXAMPLE
Remove-LocalProfile

Description
-----------
Presents a text based menu for the user to interactively remove a local profile on local or remote machine.
#>

#Prompt for a computer to connect to
$computer = "cg-ws-134"
#Test network connection before making connection
If ($computer -ne $Env:Computername) {
If (!(Test-Connection -comp $computer -count 1 -quiet)) {
Write-Warning "$computer is not accessible, please try a different computer or verify it is powered on."
Break
}
}
Try {
#Verify that the OS Version is 6.0 and above, otherwise the script will fail
If ((Get-WmiObject -ComputerName $computer Win32_OperatingSystem -ea stop).Version -lt 6.0) {
Write-Warning "The Operating System of the computer is not supported.nClient&#58; Vista and abovenServer: Windows 2008 and above."
Break
}
}
Catch {
Write-Warning "$($error[0])"
Break
}
Do {
#Gather all of the user profiles on computer
Try {
[array]$users = Get-WmiObject -ComputerName $computer Win32_UserProfile -filter "LocalPath Like ‘C:\Users\%’" -ea stop
}
Catch {
Write-Warning "$($error[0]) "
Break
}
#Cache the number of users
$num_users = $users.count

Write-Host -ForegroundColor Green "User profiles on $($computer):"

#Begin iterating through all of the accounts to display
For ($i=0;$i -lt $num_users; $i++) {
Write-Host -ForegroundColor Green "$($i): $(($users[$i].localpath).replace(‘C:\Users',’‘))"
}
Write-Host -ForegroundColor Green "q: Quit"
#Prompt for user to select a profile to remove from computer
Do {
$account = Read-Host "Select a number to delete local profile or ‘q’ to quit"
#Find out if user selected to quit, otherwise answer is an integer
If ($account -NotLike "q*") {
$account = $account -as [int]
}
}
#Ensure that the selection is a number and within the valid range
Until (($account -lt $num_users -AND $account -match "\d") -OR $account -Like "q*")
If ($account -Like "q*") {
Break
}
Write-Host -ForegroundColor Yellow "Deleting profile: $(($users[$account].localpath).replace(‘C:\Users',’’))"
#Remove the local profile
($users[$account]).Delete()
Write-Host -ForegroundColor Green "Profile: $(($users[$account].localpath).replace(‘C:\Users',’')) has been deleted"

#Configure yes choice
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Remove another profile."

#Configure no choice
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No","Quit profile removal"

#Determine Values for Choice
$choice = [System.Management.Automation.Host.ChoiceDescription[]] @($yes,$no)

#Determine Default Selection
[int]$default = 0

#Present choice option to user
$userchoice = $host.ui.PromptforChoice("","Remove Another Profile?",$choice,$default)
}
#If user selects No, then quit the script
Until ($userchoice -eq 1)


They both follow similar methodology. However I couldn’t user the ($users[$account]).Delete() as I am not asking for a selection.

Thanks for the quick reply. I have everything working, but that deleting the profile and folder section which would be a one line of code… :frowning:
by cmore86 at 2012-08-31 11:44:25
When attempting gwmi win32_Userprofile | where {$.LocalPath -like "c:\users\test"} I get nothing, it does not spit out an error and it does not remove the folder or profile. Unless I am missing a delete statement…
by DonJ at 2012-08-31 11:45:28
So, if you get nothing, that’s because there’s nothing to get. That’s not an error condition in PowerShell’s worldview.

Fortunately, the author of that original code hangs out here. Let me call his attention to this.
by JeffH at 2012-08-31 11:49:56
I wrote an article last year on this topic and also came up with some PowerShell functions to manage user profiles. http://bit.ly/soWBGY
by cmore86 at 2012-08-31 13:05:27
Attempting $userdelete | Remove-WmiObject seems to do the trick however I still get this error.


Remove-WmiObject :
At C:\DUFS3.ps1:17 char:34
+ $userdelete | Remove-WmiObject <<<<
+ CategoryInfo : NotSpecified: (:slight_smile: [Remove-WmiObject], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.RemoveWmiObject
by proxb at 2012-08-31 14:28:28
Has the account that you want to remove the profile on been logged out? I was able to reproduce your error by keeping an account logged onto my system and attempting to remove it using Remove-WMIObject. Take a look at the Loaded property in the Win32_UserProfile class and if it is True, then you will not be able to remove it.
by cmore86 at 2012-09-04 06:27:17
Where can I find that property? I know most of these users have not been logged on in at least a few weeks to a few months.
by RichardSiddaway at 2012-09-04 11:41:11
You could try something like this to test if a user of a particular profile is logged on

Get-WmiObject -Class Win32_UserProfile |
foreach {

$filt = Split-Path -Path $($.LocalPath) -Leaf
$loggedon = $null
$loggedon = Get-WmiObject Win32_loggedonuser | where {$
.Antecedent -like "Name=$filt*"} | select -First 1

$log = $false
if ($loggedon){$log = $true}

New-Object -TypeName PSObject -Property @{
Name = $filt
Logged = $log
}
}
by cmore86 at 2012-09-04 12:05:37
Thank you that was very helpful.

However running that check these users are not logged on. So not sure where I am getting stuck on.
by RichardSiddaway at 2012-09-04 12:29:46
Sorry I don’t understand where you are getting stuck
by cmore86 at 2012-09-04 12:37:24
Sorry, your powershell script works great.

I was referring to the error I still get, even if the user is not listed as logged on.


elaineh - Will be Destroyed.
Remove-WmiObject :
At C:\DUFS3.ps1:15 char:34
+ $userdelete | Remove-WmiObject <<<<
+ CategoryInfo : NotSpecified: (:slight_smile: [Remove-WmiObject], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.RemoveWmiObject


It works on most profiles, but gets stuck on a select few when running my modified script.
by proxb at 2012-09-05 09:53:12
What do you get when you run the following coded:
Get-WMIObject -Class Win32_UserProfile | Select LocalPath,Loaded
If the profile in question has True for Loaded, then you will not be able to remove the profile as it is still loaded for whatever reason.

From what it sounds like, this may or may not be the case, but at least it can be ruled out.
by cmore86 at 2012-09-05 11:09:34
Yeah that seems the case, I have tested this out and it works as it is supposed to. $computer = "cg-ts-16"
[array]$users = Get-WmiObject -ComputerName $computer Win32_UserProfile -filter "LocalPath Like ‘C:\Users\%’" -ea stop
$num_users = $users.count
Write-Host -ForegroundColor Green "User profiles on $($computer):"
For ($i=0;$i -lt $num_users; $i++)
{ $username = "$(($users[$i].localpath).replace(‘C:\Users',’’))"
$userdelete = $users
$searcher = new-object DirectoryServices.DirectorySearcher([ADSI]“”)
$searcher.filter = “(&(objectClass=user)(sAMAccountName= $username))”
$founduser = $searcher.findOne()
$user = $founduser.Properties.useraccountcontrol
if ($user -eq 514)
{
$userdelete | Remove-WmiObject
Write-Host "$username - Was Destroyed." -foregroundcolor "blue"
}
elseif ($user -eq 512)
{
Write-Host "$username - You live another day."-foregroundcolor "green"
}
elseif ($user -eq $null)
{
$userdelete | Remove-WmiObject
Write-Host "$username was exterminated."-foregroundcolor "blue"
}}


I have tested it out on several of our servers and it is removing these profiles as intended. However, I managed to completely remove all the users from one of the servers using a modified script.

Thank you everyone for your assistance.