Удаление старых профилей пользователей в Windows

Администраторы время от времени должны удалять старые профили пользователей (уволенные пользователи, неактивные пользователи, и т.д.) в каталоге C:\Users на рабочих станциях и серверах Windows. Чаще всего с задачей очисткой профилей пользователей Windows сталкиваются на терминальных серверах RDS (Remote Desktop Services).

Основная проблема терминальных серверов – постоянный рост размеров каталогов профилей пользователей на диске. Частично эта проблема решается политиками квотирования размера профиля пользователя с помощью FSRM или NTFS квот, использованием профилей типа FSLogix или User Profile Disk, перемещаемыми папками и т.д. Но при большом количестве RDS пользователей в папке C:\Users со временем накапливается огромное количество каталогов с неиспользуемыми профилями пользователей.

Как вручную удалить профиль пользователя в Windows?

 

В Windows вы можете вручную удалить профиль пользователя через панель управления.

  1. Откройте Advanced System Settings (команда SystemPropertiesAdvanced ) -> User Profiles -> Settings;
  2. В этом окне перечислен список всех профилей пользователей (локальных и доменных), которые хранятся на этом компьютере. Размер каждого профиля пользователя на диске указан в столбце Size.
  3. Выберите пользователя, чей профиль нужно удалить и нажмите кнопку Delete.Удалить с диска профиль пользователя Windows вручную

В Windows 11/10 и Windows Server 2022/2019 вы можете удалить профили пользователей с диска через приложение Settings. Перейдите в раздел Accounts -> Access work and school (или выполните команду быстрого доступа ms-settings:otherusers ). Выберите пользователя и нажмите Remove чтобы удалить его данные с компьютера.

ms-settings: удалить с диска профиль пользователя windows 11

При корректном удалении профиля пользователя с диска будет удален каталог профиля в C:\Users и запись о пользователе в реестре.

Многие начинающиеся администраторы пытаются вручную удалить каталог с профилем пользователя из папки C:\Users. В этом случае нужно обязательно вручную удалить информацию о профиле из реестра Windows:

  1. Откройте редактор реестра regedit.exe ;
  2. Перейдите в ветку HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
  3. Для каждого пользователя, выполнившего локальный вход в систему (этот метод входа должен быть разрешен пользователю настройками параметра Allow log on locally в GPO), создается отдельная ветка с SID пользователя в качестве имени;
  4. Вы можете найти раздел реестра, соответствующий пользователю по SID, или можете вручную просмотреть содержимое всех вложенных разделв, пока не найдете раздел, в котором значение ProfileImagePath указывает на каталог с профилем пользователя на диске (например, C:\Users\kbuldogov );путь к профилю пользователя в реестре ProfileImagePath
  5. Удалите данный раздел реестра, чтобы завершить корректное удаление профиля.

Также вы можете удалить профиль конкретного пользователя с помощью PowerShell:

Get-CimInstance -Class Win32_UserProfile | Where-Object { $_.LocalPath.split(‘\’)[-1] -eq 'kbuldogov' } | Remove-CimInstance

Эта команда удалит как каталог на диске, так и ссылку на профиль пользователя kbuldogov в реестре HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList.

Эта команда будет работать как в Windows PowerShell, так и в новых версиях PowerShell Core 6.x,7.x

Можно удалить профиль пользователя на удаленном компьютере с помощью 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.

Прежде чем применять политику удаления старых профилей ко всем хостам, настоятельно рекомендуем проверить ее на тестовом сервере. Выведите один из серверов RDSH в режим обслуживания и протестируйте политику на нем.
  1. Найдите OU с компьютерами/серверами, на который вы хотите применить политику очистки старых профилей пользователей. Щелкните по OU и выберите Create a GPO in this domain and Link it here;gpo создать политику для удаления старых и неактивных профилей
  2. Укажите имя политики и отредактируйте GPO;
  3. Перейдите в раздел Конфигурация компьютера -> Административные шаблоны -> Система -> Профили пользователей (Computer Configuration -> Administrative Templates -> System -> User Profiles);
  4. Откройте параметр “Удалять при перезагрузке системы профили пользователей по истечении указанного числа дней” (Delete user profiles older than a specified number days on system restart);
  5. Включите политику и укажите через сколько дней профиль пользователя считается неактивным и “Служба профилей пользователей Windows” можно автоматически удалить такой профиль при следующей перезагрузке. Обычно тут стоит указать не менее 45-90 дней;gpo удалить профили старше 60 дней при перезагрузке
  6. После применения новых настроек групповых политк, служба 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_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\<User Sid> .

LocalProfileLoadTimeLow в ветке реестра ProfileList

Вы можете получить значения параметров реестра 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 } }

получить время последнего входа в профиль в windows

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 Гб.

суммарный размер всех профилей пользвоателей

При расчете размера профиля пользователя скрипт игнорирует символические ссылки в Windows.

Теперь выведем список пользователей, профиль которых не использовался более 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 = @()
$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

Как мы уже упомянули выше, при установке некоторых обновлений 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 скрипт групповой политики или по расписанию заданием планировщика. (перед настройкой автоматического удаления профилей внимательно протестируйте скрипт в своей среде!).

Можно модифицировать скрипт, чтобы автоматически удалять пользователи всех пользователей, которые добавлены в определенную группу AD. Например, вы хотите автоматически удалять профили уволившихся пользователей. Просто добавьте такие учетные записи в группу DisabledUsers и выполните на сервере скрипт:

$users = Get-ADGroupMember -Identity DisabledUsers | Foreach {$_.Sid.Value}
$profiles = Get-WmiObject Win32_UserProfile
$profiles | Where {$users -eq $_.Sid} | Foreach {$_.Delete()}

Дополнительно вы можете использовать еще один PowerShell скрипт для очистки временных файлов и кэша в профилях активных пользователей RDS

Предыдущая статья Следующая статья


Комментариев: 32 Оставить комментарий

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Я не робот( Обязательно отметьте)