Администраторы должны время от времени удалять старые профили пользователей (вышедших на пенсию, неактивных пользователей и т. д.) из папки C:\Users на рабочих станциях и серверах Windows. Задача очистки профилей пользователей в Windows чаще всего выполняется на терминальных серверах Remote Desktop Services (RDS).
Основной проблемой RDS-серверов является постоянный рост размера каталогов пользовательских профилей на жестком диске. Эта проблема частично решается с помощью квот на размер пользовательских профилей, использующих FSRM или NTFS-квоты, перемещаемых профилей, таких как FSLogix или User Profile Disk, перенаправляемых папок и т. д. Однако если у вас большое количество пользователей RDS, со временем папка C:\Users будет содержать большое количество каталогов со старыми (неиспользуемыми) профилями пользователей.
Как удалить профиль пользователя в Windows вручную?
В Windows профиль можно удалить вручную из панели управления:
- Откройте Дополнительные настройки системы (выполните команду
SystemPropertiesAdvanced
) и перейдите к Профили пользователей -> Настройки; - В этом окне перечислены все профили пользователей (локальные, доменные и учетные записи Microsoft), хранящиеся на этом компьютере. Размер каждого профиля пользователя на диске указан в поле Размер рубрика;
- Выберите пользователя, профиль которого вы хотите удалить, и нажмите кнопку Удалить кнопка.
В Windows 11/10 и Windows Server 2022/2019 профили пользователей можно удалить с диска с помощью команды Настройки приложение. Перейдите к Счета -> Доступ к работе и школе (или запустите ярлык URI ms-settings:otherusers
). Выберите пользователя и нажмите кнопку Удалить чтобы удалить данные своего профиля с компьютера.
При правильном удалении профиля пользователя в Windows удаляется каталог профиля в C:\Users и запись пользователя в реестре.
Многие начинающие администраторы пытаются вручную удалить каталог профиля пользователя из папки C:\Users. В этом случае необходимо вручную удалить ссылку на профиль из реестра Windows:
- Запустите редактор реестра (
regedit.exe
); - Перейдите к ключу реестра HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList;
- Для каждого пользователя, вошедшего в систему локально (этот способ входа должен быть разрешен для пользователя параметром Разрешить вход в систему локально Опция GPO), создается отдельный подключ с SID пользователя в качестве имени;
- Вы можете найти ключ реестра, соответствующий пользователю, по его SID, или вручную просмотреть содержимое всех подключей, пока не найдете ключ, в котором ProfileImagePath значение указывает на каталог с профилем пользователя на диске (например,
C:\Users\j.smith
); - Удалите этот ключ реестра, чтобы завершить корректное удаление профиля.
Можно также удалить профиль конкретного пользователя с помощью PowerShell:
Get-CimInstance -Class Win32_UserProfile | Where-Object { $_.LocalPath.split(‘\’)[-1] -eq 'j.smith' } | Remove-CimInstance
Эта команда удаляет как каталог жесткого диска, так и j.smith
ссылку на профиль пользователя в реестре HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList.
Вы можете удалить профиль пользователя на удаленном компьютере с помощью PowerShell Remoting и команды Invoke-Command:
$compname="mun-wks92s3"
$user = "j.smith"
Invoke-Command -ComputerName $compname -ScriptBlock {
param($user)
Get-CimInstance -Class Win32_UserProfile | Where-Object { $_.LocalPath.split(‘\’)[-1] -eq $user } | Remove-CimInstance
} -ArgumentList $user
GPO: Удаление пользовательских профилей старше указанного количества дней
В Windows есть встроенная опция групповой политики для автоматического удаления пользовательских профилей старше xx дней. Включить эту опцию можно с помощью редактора локальной групповой политики (gpedit.msc
) или с помощью консоли управления GPO домена (gpmc.msc
). В этом примере мы применим политику автоматической очистки профиля к узлам в ферме RDS, которые находятся в отдельном контейнере (Organizational Unit, OU) в Active Directory.
- Найдите OU, содержащую компьютеры/серверы, к которым вы хотите применить политику очистки пользовательских профилей. Щелкните правой кнопкой мыши на OU и выберите Создать GPO в этом домене и связать его здесь;
- Укажите имя политики и отредактируйте GPO;
- Перейдите в Конфигурация компьютера -> Административные шаблоны -> Система -> Профили пользователей;
- Открыть опцию Удаление профилей пользователей старше указанного количества дней при перезагрузке системы;
- Включите политику и укажите количество дней, в течение которых профиль пользователя считается активным. По истечении этого срока служба Windows User Profile Service автоматически удалит профиль при следующем перезапуске. Рекомендуется указать 45-90 дни здесь;
- После применения новых параметров групповой политики служба профилей пользователей на сервере Windows Server будет автоматически удалять старые профили пользователей. Профили пользователей будут удалены при следующей перезагрузке сервера.
Эта политика некорректно работала в версиях до Windows 11/10 и Windows Server 2022/2019. Ранее неактивность профиля пользователя определялась по дате изменения файла NTUSER.dat. При установке обновлений Windows служба Trusted Installer может изменить дату модификации файла NTUSER.dat файл в профиле каждого пользователя. В результате служба Win32_UserProfile считает, что профиль недавно использовался.
В современных версиях Windows этот параметр групповой политики проверяет активность пользовательского профиля по значениям параметра LocalProfileUnloadTimeLow и LocalProfileUnloadTimeHigh параметры в HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\<USER_SID>
Вы можете использовать следующий сценарий, чтобы получить LocalProfileLoadTimeLow и LocalProfileUnloadTimeHigh значения реестра в формате обычного времени:
$profilelist = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" foreach ($p in $profilelist) { try { $objUser = (New-Object System.Security.Principal.SecurityIdentifier($p.PSChildName)).Translate([System.Security.Principal.NTAccount]).value } catch { $objUser = "[UNKNOWN]" } Remove-Variable -Force LTH,LTL,UTH,UTL -ErrorAction SilentlyContinue $LTH = '{0:X8}' -f (Get-ItemProperty -Path $p.PSPath -Name LocalProfileLoadTimeHigh -ErrorAction SilentlyContinue).LocalProfileLoadTimeHigh $LTL = '{0:X8}' -f (Get-ItemProperty -Path $p.PSPath -Name LocalProfileLoadTimeLow -ErrorAction SilentlyContinue).LocalProfileLoadTimeLow $UTH = '{0:X8}' -f (Get-ItemProperty -Path $p.PSPath -Name LocalProfileUnloadTimeHigh -ErrorAction SilentlyContinue).LocalProfileUnloadTimeHigh $UTL = '{0:X8}' -f (Get-ItemProperty -Path $p.PSPath -Name LocalProfileUnloadTimeLow -ErrorAction SilentlyContinue).LocalProfileUnloadTimeLow $LoadTime = if ($LTH -and $LTL) { [datetime]::FromFileTime("0x$LTH$LTL") } else { $null } $UnloadTime = if ($UTH -and $UTL) { [datetime]::FromFileTime("0x$UTH$UTL") } else { $null } [pscustomobject][ordered]@{ User = $objUser SID = $p.PSChildName Loadtime = $LoadTime UnloadTime = $UnloadTime } }
Этот список содержит время последней загрузки для каждого пользовательского профиля.
Удаление старых профилей пользователей с помощью сценария PowerShell
Вместо использования описанной выше политики автоматической очистки профилей можно использовать простой сценарий PowerShell для поиска и удаления профилей отключенных или неактивных пользователей.
Сначала попробуем рассчитать размер профиля каждого пользователя в C:\Users с помощью простого сценария из статьи Получение размера папки с помощью PowerShell
gci -force ‘C:\Users\’-ErrorAction SilentlyContinue | Where { !($_.Attributes -match " ReparsePoint") }| ? { $_ -is [io.directoryinfo] } | % {
$len = 0
gci -recurse -force $_.fullname -ErrorAction SilentlyContinue | % { $len += $_.length }
$_.fullname, ‘{0:N2} GB’ -f ($len / 1Gb)
$sum = $sum + $len
}
"Total size of profiles",'{0:N2} GB' -f ($sum / 1Gb)
Общий размер всех профилей пользователей в C:\Users составляет около 32 ГБ.
Посмотрим список пользователей, чьи профили не использовались более 60 дней. Вы можете использовать значение в поле LastUseTime поле профиля, чтобы найти их.
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-60))}| Measure-Object
Оказалось, что на моем хосте RDS было 127 неактивных учетных записей пользователей (с профилями общим размером около 18 ГБ).
Следующий сценарий PowerShell выводит список сведений о профилях пользователей, которые не обновлялись более 60 дней. Сценарий преобразует SID пользователя в имя, вычисляет размер профиля каждого пользователя и выводит итоговую таблицу:
$allprofilesinfo = @() $OldProfiles=Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-60))} Foreach ($OldProfile in $OldProfiles) {$objSID = New-Object System.Security.Principal.SecurityIdentifier ($OldProfile.SID) $objUser = $objSID.Translate( [System.Security.Principal.NTAccount]) $userinfo = New-Object PSObject -Property @{ userName = $objUser.Value ProfilePath = $OldProfile.localpath LastUsedDate = $OldProfile.ConvertToDateTime($OldProfile.LastUseTime) FolderSize = "{0:N2} GB" -f ((gci –force $OldProfile.localpath –Recurse -ErrorAction SilentlyContinue| measure Length -s).sum / 1Gb) } $allprofilesinfo += $userinfo } $allprofilesinfo
Чтобы удалить все эти профили пользователей, достаточно передать список пользователей в файл Remove-WmiObject (рекомендуется проверить вывод скрипта с помощью команды -WhatIf параметр перед запуском):
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and (!$_.Loaded) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))} | Remove-WmiObject –WhatIf
gwmi win32_quickfixengineering |sort installedon |select InstalledOn -Last 1
Или с помощью модуля PSWindowsUpdate:
Get-WUHistory | Select-Object -First 10
Скорее всего, это совпадет с датой изменения профилей. Поэтому на более ранних версиях Windows список неактивных профилей можно получить с помощью другого сценария, который проверяет значение lastwritetime атрибут каталога профиля пользователя:
$USERS= (Get-ChildItem -directory -force 'C:\Users' | Where { ((Get-Date) — $_.lastwritetime).days -ge 60 } | % {'c:\users\' + $_.Name})
foreach ($User in $USERS) {
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and (!$_.Loaded) -and ($_.LocalPath -eq $User)} | Remove-WmiObject WhatIf }
Чтобы избежать удаления профилей некоторых пользователей (например Система и Сетевая служба учетные записи, a локальный администратор учетную запись, учетные записи пользователей, имеющих активные сеансы, и другие учетные записи из исключение список), вы можете модифицировать скрипт следующим образом:
#The list of accounts, which profiles must not be deleted
$ExcludedUsers ="Public","zabbix_agent","svc",”user_1”,”user_2”
$LocalProfiles=Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and (!$_.Loaded) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-60))}
foreach ($LocalProfile in $LocalProfiles)
{
if (!($ExcludedUsers -like $LocalProfile.LocalPath.Replace("C:\Users\","")))
{
$LocalProfile | Remove-WmiObject
Write-host $LocalProfile.LocalPath, "profile deleted” -ForegroundColor Magenta
}
}
Вы можете запустить этот сценарий PowerShell через GPO при выключении или с помощью сценария PowerShell в планировщике задач.
Можно изменить сценарий для автоматического удаления всех профилей пользователей, добавленных в определенную группу AD. Например, вы хотите удалить профили пользователей, которые уволились. Просто добавьте эти учетные записи в группу DisabledUsers группу и запустите сценарий на целевом хосте:
$users = Get-ADGroupMember -Identity DisabledUsers | Foreach {$_.Sid.Value}
$profiles = Get-WmiObject Win32_UserProfile
$profiles | Where {$users -eq $_.Sid} | Foreach {$_.Delete()}