Администраторы время от времени должны удалять старые профили пользователей (уволенные пользователи, неактивные пользователи , и т.д.) в каталоге C:Users на рабочих станциях и серверах Windows. Чаще всего с задачей очисткой профилей пользователей Windows сталкиваются на терминальных серверах RDS (Remote Desktop Services).
Основная проблема терминальных серверов – постоянный рост размеров каталогов профилей пользователей на диске. Частично эта проблема решается политиками квотирования размера профиля пользователя с помощью FSRM или NTFS квот , использованием профилей типа FSLogix или User Profile Disk , перемещаемыми папками и т.д. Но при большом количестве RDS пользователей в папке C:Users со временем накапливается огромное количество каталогов с неиспользуемыми профилями пользователей.
Как вручную удалить профиль пользователя в Windows?
В Windows вы можете вручную удалить профиль пользователя через панель управления.
- Откройте Advanced System Settings (команда
SystemPropertiesAdvanced
) -> User Profiles -> Settings ; - В этом окне перечислен список всех профилей пользователей (локальных и доменных), которые хранятся на этом компьютере. Размер каждого профиля пользователя на диске указан в столбце Size.
- Выберите пользователя, чей профиль нужно удалить и нажмите кнопку Delete .
В Windows 11/10 и Windows Server 2022/2019 вы можете удалить профили пользователей с диска через приложение Settings. Перейдите в раздел Accounts -> Access work and school (или выполните команду быстрого доступа ms-settings:otherusers
). Выберите пользователя и нажмите Remove чтобы удалить его данные с компьютера.
При корректном удалении профиля пользователя с диска будет удален каталог профиля в C:Users и запись о пользователе в реестре.
Многие начинающиеся администраторы пытаются вручную удалить каталог с профилем пользователя из папки C:Users. В этом случае нужно обязательно вручную удалить информацию о профиле из реестра Windows:
- Откройте редактор реестра
regedit.exe
; - Перейдите в ветку HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionProfileList
- Для каждого пользователя, выполнившего локальный вход в систему (этот метод входа должен быть разрешен пользователю настройками параметра Allow log on locally в GPO ) , создается отдельная ветка с SID пользователя в качестве имени;
- Вы можете найти раздел реестра, соответствующий пользователю по SID, или можете вручную просмотреть содержимое всех вложенных разделв, пока не найдете раздел, в котором значение ProfileImagePath указывает на каталог с профилем пользователя на диске (например,
C:Userskbuldogov
); - Удалите данный раздел реестра, чтобы завершить корректное удаление профиля.
Также вы можете удалить профиль конкретного пользователя с помощью PowerShell:
Get-CimInstance -Class Win32_UserProfile | Where-Object { $_.LocalPath.split(‘’)[-1] -eq 'kbuldogov' } | Remove-CimInstance
Эта команда удалит как каталог на диске, так и ссылку на профиль пользователя kbuldogov в реестре HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionProfileList.
Можно удалить профиль пользователя на удаленном компьютере с помощью PowerShell Remoting и командлета Invoke-Command :
$compname="wks21s32"
$user = "kbuldogov"
Invoke-Command -ComputerName $compname -ScriptBlock {
param($user)
Get-CimInstance -Class Win32_UserProfile | Where-Object { $_.LocalPath.split(‘’)[-1] -eq $user } | Remove-CimInstance
} -ArgumentList $user
Групповая политика для автоматической очистки старых профилей
В Windows есть специальный параметр групповой политики для автоматического удаления старых профилей пользователей старше xx дней. Вы можете включить этот параметр с помощью локального редактора GPO ( gpedit.msc
) или с помощью консоли управления доменными GPO ( gpmc.msc
). В этом примере на назначим политику автоматической очистки профилей на хосты в ферме RDS , которые вынесены в отдельный контейнер ( Organizational Unit ) Active Directory.
- Найдите OU с компьютерами/серверами, на который вы хотите применить политику очистки старых профилей пользователей. Щелкните по OU и выберите Create a GPO in this domain and Link it here ;
- Укажите имя политики и отредактируйте GPO;
- Перейдите в раздел Конфигурация компьютера -> Административные шаблоны -> Система -> Профили пользователей (Computer Configuration -> Administrative Templates -> System -> User Profiles);
- Откройте параметр “ Удалять при перезагрузке системы профили пользователей по истечении указанного числа дней ” (Delete user profiles older than a specified number days on system restart);
- Включите политику и укажите через сколько дней профиль пользователя считается неактивным и “Служба профилей пользователей Windows” можно автоматически удалить такой профиль при следующей перезагрузке. Обычно тут стоит указать не менее 45-90 дней;
- После применения новых настроек групповых политк , служба User Profile Services на ваших серверах Windows будет автоматически удалять старые профили пользователей. Удаление выполняется при перезагрузке сервера.
Другой недостаток — вы не можете запретить удаление определенных профилей, например, локальных учетных записей, администраторов и т.д.
В версиях до Windows 11/10 и Windows Server 2022/2019 эта политика работала некорректно. Дело в том, что неактивноть профиля пользователя ранее определялась по дате именения файла NTUSER.dat . При установке обновлений Windows, служба Trusted Installer может менять дату изменения файла NTUSER.dat в профиле каждого пользователя. В результате служба Win32_UserProfile считает, что профиль использовался недавно.
В современных версиях Windows эта политика проверяет активность профиля пользователей по параметрам LocalProfileUnloadTimeLow и LocalProfileUnloadTimeHigh в ветке HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionProfileList<User Sid>
.
$profilelist = Get-ChildItem "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionProfileList"_x000D_foreach ($p in $profilelist) {_x000D_ try {_x000D_ $objUser = (New-Object System.Security.Principal.SecurityIdentifier($p.PSChildName)).Translate([System.Security.Principal.NTAccount]).value_x000D_ } catch {_x000D_ $objUser = "[UNKNOWN]"_x000D_ }_x000D_ Remove-Variable -Force LTH,LTL,UTH,UTL -ErrorAction SilentlyContinue_x000D_ $LTH = '{0:X8}' -f (Get-ItemProperty -Path $p.PSPath -Name LocalProfileLoadTimeHigh -ErrorAction SilentlyContinue).LocalProfileLoadTimeHigh_x000D_ $LTL = '{0:X8}' -f (Get-ItemProperty -Path $p.PSPath -Name LocalProfileLoadTimeLow -ErrorAction SilentlyContinue).LocalProfileLoadTimeLow_x000D_ $UTH = '{0:X8}' -f (Get-ItemProperty -Path $p.PSPath -Name LocalProfileUnloadTimeHigh -ErrorAction SilentlyContinue).LocalProfileUnloadTimeHigh_x000D_ $UTL = '{0:X8}' -f (Get-ItemProperty -Path $p.PSPath -Name LocalProfileUnloadTimeLow -ErrorAction SilentlyContinue).LocalProfileUnloadTimeLow_x000D_ $LoadTime = if ($LTH -and $LTL) {_x000D_ [datetime]::FromFileTime("0x$LTH$LTL")_x000D_ } else {_x000D_ $null_x000D_ }_x000D_ $UnloadTime = if ($UTH -and $UTL) {_x000D_ [datetime]::FromFileTime("0x$UTH$UTL")_x000D_ } else {_x000D_ $null_x000D_ }_x000D_ [pscustomobject][ordered]@{_x000D_ User = $objUser_x000D_ SID = $p.PSChildName_x000D_ Loadtime = $LoadTime_x000D_ UnloadTime = $UnloadTime_x000D_ }_x000D_} _x000D_
PowerShell скрипт для удаления старых профилей пользователей в Windows
Вы можете удалять профили неактивных или заблокированных пользователей с помощью скрипта PowerShell.
Сначала попробуем подсчитать размер профиля каждого пользователя в папке C:Users c помощью простого скрипта из статьи “ Вывести размер папок с помощью 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
}
“Общий размер профилей”,'{0:N2} GB’ -f ($sum / 1Gb)
Итого суммарный размер всех профилей пользователей в каталоге C:Users около 22 Гб.
Теперь выведем список пользователей, профиль которых не использовался более 60 дней. Для поиска можно использовать значение атрибута профиля LastUseTime.
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-60))}| Measure-Object
У меня на терминальном сервере оказалось 143 профиля неактивных пользователей (общим размером около 10 Гб).
Следующий PowerShell скрипт выведет список подробную информацию о профилях пользователей, которые не обновлялись более 60 дней. Скрипт сконвертирует SID пользователя в имя , посчитает размер профиля каждого пользователя и выведет все в таблице:
$allprofilesinfo = @()_x000D_$OldProfiles=Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-60))}_x000D_Foreach ($OldProfile in $OldProfiles)_x000D_ {$objSID = New-Object System.Security.Principal.SecurityIdentifier ($OldProfile.SID)_x000D_ $objUser = $objSID.Translate( [System.Security.Principal.NTAccount])_x000D_ $userinfo = New-Object PSObject -Property @{_x000D_ userName = $objUser.Value_x000D_ ProfilePath = $OldProfile.localpath_x000D_ LastUsedDate = $OldProfile.ConvertToDateTime($OldProfile.LastUseTime)_x000D_ FolderSize = "{0:N2} GB" -f ((gci –force $OldProfile.localpath –Recurse -ErrorAction SilentlyContinue| measure Length -s).sum / 1Gb) _x000D_ }_x000D_ $allprofilesinfo += $userinfo_x000D_ }_x000D_$allprofilesinfo _x000D_
Чтобы удалить все эти профили достаточно добавить перенаправить список на команду Remove-WmiObject (перед использование скрипта удаления желательно несколько раз перепроверить его вывод с помощью параметра –WhatIf ):
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and (!$_.Loaded) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))} | Remove-WmiObject –WhatIf
Как мы уже упомянули выше, при установке некоторых обновлений Windows, служба Trusted installer может менять дату изменения файла NTUSER.dat в профиле каждого пользователя.
На скриншоте выше видно, что все профили были изменены примерно в одно и тоже время. Проверьте дату последней установки обновлений в Windows:
gwmi win32_quickfixengineering |sort installedon |select InstalledOn -Last 1
Или с помощью модуля PSWindowsUpdate :
Get-WUHistory | Select-Object -First 20
Скорее всего она совпадет с датой изменения профилей. Поэтому в старых версиях 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 }
Чтобы не удалять профили некоторых пользователей, например, специальные аккаунты System и Network Service, учетную запись локального администратора, пользователей с активными сессиями, список аккаунтов-исключений), нужно модифицировать скрипт следующим образом:
#Список аккаунтов, чьи профили нельзя удалять
$ExcludedUsers ="Public","zenoss","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профиль удален” -ForegroundColor Magenta
}
}
Вы можете настроить запуск этого скрипта через shutdown скрипт групповой политики или по расписанию заданием планировщика . (перед настройкой автоматического удаления профилей внимательно протестируйте скрипт в своей среде!).
Можно модифицировать скрипт