I have the script where it captures blank profile paths in the profile list. I am not sure how to call the array and delete the whole key. It is saying path is not found as it is trying to run it from c:\windows\system32
how do i get it to go through the different paths it might have ? Right now I am just testing by blanking out one profile path
$Profiles = get-childitem “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList”
$ProfileData = @()
foreach($Profile in $Profiles){
$ThisProfileInfo = $null
$ThisProfileInfo = @{Name=$Profile.Name;
ProfilePath=$Profile.GetValue("ProfileImagePath")}
if (!($ThisProfileInfo.ProfilePath)) {
$ProfileData = $ThisProfileInfo
}
}
$ProfileData
ForEach-Object{Remove-Item -Path ($Object.name)}
the error is ForEach-Object{Remove-Item -Path ($Object.name)}
Name Value
---- -----
Name HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-21-115761338-1150813220-1225219381-227283
ProfilePath
Remove-Item : Cannot find path 'C:\WINDOWS\system32\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\ProfileList\S-1-5-21-115761338-1150813220-1225219381-227283' because it does not exist.
At line:24 char:16
ForEach-Object{Remove-Item -Path ($Object.name)}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (C:\WINDOWS\syst...25219381-227283:String) [Remove-Item], ItemNotFoundException
FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
CodePudding user response:
tl;dr
The following removes all registry keys representing user profiles that have no / an empty ProfileImagePath
value:
# Note: Run with elevation, otherwise Remove-Item will fail.
Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" |
Where-Object { -not $_.GetValue('ProfileImagePath') } |
Remove-Item -WhatIf
Note: The -WhatIf
common parameter in the command above previews the operation. Remove -WhatIf
once you're sure the operation will do what you want.
Your primary problem is that the .Name
property of items representing registry keys is a registry-native key path (e.g. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-18
), which PowerShell's Remove-Item
doesn't recognize as such[1] and interprets as a relative file-system path.
There's also an incidental syntax problem in your question, as of this writing: your last two statements should be a single pipeline, as follows:
$ProfileData | ForEach-Object{ Remove-Item -Path $_.Name }
Piping the Get-ChildItem
output directly to Remove-Item
avoids this problem, because it binds the .PSPath
property values to Remove-Item
's -LiteralPath
parameter, and .PSPath
contains a provider-qualified path, i.e. it has a prefix that identifies the path as a registry path; e.g. Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-18
For details on where the .PSPath
property values come from and how they bind to the -LiteralPath
parameter of PowerShell's provider cmdlets, see this answer.
[1] There is one exception: If the current location (as reflected in $PWD
/ Get-Location
) happens to be the root of the targeted registry hive (which would be unusual, because registry locations are rarely made the current location), the registry-native path is recognized. E.g, if you changed to the root of the HKEY_LOCAL_MACHINE
hive with Set-Location HKLM:\
,
Get-ChildItem HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
would work (with or without the HKEY_LOCAL_MACHINE\
prefix).
CodePudding user response:
It would be best to troubleshoot by running just:
get-childitem “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList”
When I ran this, I got two fields: Name
and Property
. The name field only had the name of the key, but when I ran:
get-childitem “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList” | select Name
I was able to get the full path to the key, which may be why the prior method wasn't working. Might just need to add | select Name
.