本文中提供的示例脚本可帮助清理注册表和 C:\users 文件夹中的孤立配置文件信息。
如果配置文件不完整或未正确删除,则可以创建其他用户文件夹,或者用户在登录时可能会收到 TEMP 配置文件。 在某些情况下,可能有许多配置文件处于使用 TEMP 配置文件的状态,即使这些配置文件尚未登录。
适用于: Windows 10、Windows 11、Windows Server 2016 及更高版本
重要
此示例脚本在任何Microsoft标准支持计划或服务下都不受支持。
示例脚本按原样提供,没有任何保证。 Microsoft进一步否认所有默示担保,包括不限于适销性或针对特定用途的适用性的任何默示担保。
示例脚本和文档的使用或性能导致的整个风险依然存在。 在任何情况下,不得Microsoft、其作者或参与创建、制作或交付脚本的任何其他人对任何损害负责(包括但不限于业务利润损失、业务中断、业务中断、业务信息损失或其他经济损失)因使用或无法使用示例脚本或文档而导致的损害。 即使Microsoft被告知这种损害的可能性。
#
# usage:
# PowerShell /file OrhanedProfile.ps1 [-clean]
#
# The clean switch enables the deletion to take place. Otherwise, it reports what it could do.
#
Param(
[switch]$bClean = $false
)
# Check if running as an Administrator
if( -NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") )
{
Write-Host "Please run as a member of the Administrators group"
break
}
# Get Profiles folder
$ProfilesListRegPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
$ProfilesFolder = $null
$ProfilesFolder = Get-ItemPropertyValue -Path $ProfilesListRegPath -Name "ProfilesDirectory"
If( $ProfilesFolder -eq $null )
{
Write-Host "Error getting the base profile folder."
break
}
"Profile folder: $ProfilesFolder"
#######################################
# Begin to get and check ProfileList key information
"Collecting ProfileList key information..."
"=" * 40
$WellKnownProfiles = @("S-1-5-18","S-1-5-19","S-1-5-20")
$ProfileListCount = 0
$ProfileListWarnCount = 0
$ProfileListInfo = @{}
Get-ChildItem -Path $ProfilesListRegPath -Exclude $WellKnownProfiles | ForEach-Object `
{
$ProfileSID = $_.PSChildName
$ProfilePath = $null
$ProfilePath = Get-ItemPropertyValue -Path $_.PSPath -Name "ProfileImagePath"
if( $ProfilePath -eq $null )
{
"Unable to read ProfileImagePath from ProfileList entry: $($_.Name)"
}
else
{
$ProfileListCount++
if( $ProfileSID -like "*.bak" )
{
"WARNING: .BAK ProfileList entry exists: $ProfileSID"
$ProfileListWarnCount++
}
try{
$ProfileListInfo.Add( $ProfilePath, $ProfileSID)
}
catch
{
$ProfileListInfo[ $ProfilePath ] = $ProfileListInfo[ $ProfilePath ] + ";$ProfileSID"
"WARNING: Multiple profile entries reference '$ProfilePath': $($ProfileListInfo[$ProfilePath])"
$ProfileListWarnCount++
}
}
}
"ProfileList Count...: $ProfileListCount"
"ProfileList Warnings: $ProfileListWarnCount"
#######################################
# Check for Orphaned ProfileListEntries - entries that reference deleted profile folders
""
"Looking for orphaned ProfileListEntries"
"=" * 40
$OrphanedProfileEntries = 0
$ProfileListInfo.GetEnumerator() | ForEach-Object `
{
$bOrphaned = $false
if( -not (Test-Path -Path $_.Key ) )
{
"Entry: $($_.Value) => $($_.Name)"
$OrphanedProfileEntries++
$bOrphaned = $true
}
elseif( -not (Get-ChildItem -Path $_.Key -include ntuser.dat,ntuser.man -Name -Force -File) )
{
"MISSING NTUSER.DAT or NTUSER.MAN: $($_.Value) => $($_.Name)"
$OrphanedProfileEntries++
$bOrphaned = $true
}
if( $bOrphaned -and $bClean )
{
$_.Value.Split( ";") | ForEach-Object `
{
try
{
$WMIUserProfile = gwmi -Class Win32_UserProfile -Filter "sid = '$($_)'"
$WMIUserProfile.Delete()
"Successfully deleted orphaned profile information."
}
catch
{
"Error occurred deleting profile. It may have only been partially deleted. [$($_.Exception.Message)]"
}
}
}
}
"=" * 40
"Orphaned ProfileListEntries: $OrphanedProfileEntries"
#######################################
# Check for Orphaned ProfileGUID entries - having SidString that reference deleted SID keys under ProfileList
# ProfileGUID would only exist on machines that have been domain joined at some time
$ProfileGUIDPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGUID"
if( Test-Path -Path $ProfileGUIDPath )
{
""
"Looking for orphaned ProfileGUID entries"
"=" * 40
$OrphanedGUIDCount = 0
Get-ChildItem -Path $ProfileGUIDPath | ForEach-Object `
{
$SidString = $null
$SidString = Get-ItemPropertyValue -Path ($ProfilesListRegPath + "\" + $_.PSChildName) -Name "SidString" -ErrorAction SilentlyContinue
if( -not $SidString -eq $null )
{
if( $null -eq (Get-Item ($ProfilesListRegPath + "\" + $SidString) -ErrorAction SilentlyContinue) )
{
"Orphaned GUID: $($_.PSChildName)"
$OrphanedGUIDCount++
if( $bClean )
{
Remove-Item -Path $_.PSPath -Recurse -Force
}
}
}
}
"=" * 40
"Orphaned ProfileGUIDS: $OrphanedGUIDCount"
}
#######################################
# Check for Orphaned user folders - folders in the profile folder that are not referenced by ProfileList\SID keys
""
"Looking for orphaned user folders"
"=" * 40
$KnownUserFolders = @("All Users", "Default", "Default User", "LocalService", "NetworkService", "Public")
$OrhanedUserFolders = 0
Get-ChildItem -Path $ProfilesFolder -Exclude $KnownUserFolders -Directory -Force | ForEach-Object `
{
if( -not $ProfileListInfo.Contains( $_.FullName ) )
{
"Folder: $($_.FullName) (Created: $($_.CreationTime) - Modified $($_.LastWriteTime))"
$OrhanedUserFolders++
if( $bClean )
{
Remove-Item -Path ("\\?\$($_.FullName)") -Force -Recurse
}
}
}
"=" * 40
"Orphaned user folders: $OrhanedUserFolders"
""
"Completed."