На терминальных серверах существует проблема с автоматическим удалением перемещаемых профилей (roaming profiles), если в терминальной сессии происходил сбой какой-нибудь программы - временные файлы программы блокируют удаление профиля с терминального сервера. При следующем входе в терминальную сессию для пользователя создастся новый профиль с каким-то суфиксом, так как старый неудаленный профиль не даст корректно переместить профиль с файлового сервера на терминальный. Со временем таких неудаленных профилей накопится очень много, что замусорит систему.
Для решения вышеописанной проблемы рекомендую использовать скрипт удаления профилей с терминального сервера, который должен быть запущен сразу же после перезагрузки сервера, когда терминальные сессии к серверу еще не установлены, то есть когда на сервере по определению не может быть профилей пользователей.
Ниже приведен код скрипта удаления профилей Remove-Profiles.ps1.
# Получение пути к скрипту
$ScriptFolder = $MyInvocation.MyCommand.Path.SubString(0,($MyInvocation.MyCommand.Path.Length - `
$MyInvocation.MyCommand.Name.Length))
# Формирование пути к лог-файлу
$LogFile = $ScriptFolder + $MyInvocation.MyCommand.Name.SubString(0,($MyInvocation.MyCommand.Name.Length `
- 4)) + ".log"
# Создание лог-файла
Out-File -FilePath $LogFile
# Указание папки профилей
$ProfileFolder = "C:\Users"
# Указание служебных папок
$ExcludedProfiles = "Default", "Default User", "Public", "All Users", "Administrator"
# Получение объектов из папки профилей
$SubDirs= Get-ChildItem $ProfileFolder -Force
# Обработка объектов из папки профилей
ForEach ($Dir in $SubDirs) {
$LogMessage = $Nothing
# Проверка, что объект существует и это папка
If (Test-Path $Dir.FullName -PathType Container) {
# Проверка, что профиль - это не служебная папка
$NotDeleteFlag = $False
ForEach ($ExcludedProfile in $ExcludedProfiles) {
If ($Dir.Name -eq $ExcludedProfile) {
$NotDeleteFlag = $True
}
}
# Удаление профиля
If ($NotDeleteFlag -eq $False) {
# Формирование события для лога
$LogMessage = get-date -uformat "%d.%m.%Y %H:%M:%S"
$LogMessage += "`t"
$LogMessage += $Dir.FullName + " is deleted."
# Удаление папки
#Remove-Item -Path $Dir.FullName -Force -Recurse
$CmdLine = "cmd /c RD /S /Q """ + $Dir.FullName + """"
Invoke-Expression -command $CmdLine
}
Else {
# Формирование события для лога
$LogMessage = get-date -uformat "%d.%m.%Y %H:%M:%S"
$LogMessage += "`t"
$LogMessage += $Dir.FullName + " is skipped as a service folder."
}
}
Else {
# Формирование события для лога
$LogMessage = get-date -uformat "%d.%m.%Y %H:%M:%S"
$LogMessage += "`t"
$LogMessage += $Dir.FullName + " is skipped as a file."
}
# Запись события в лог-файл
$LogMessage | Out-File -FilePath $LogFile -Append
}
Обращаю внимание, что в скрипте закомментирована строка удаления папок средствами PowerShell
Remove-Item -Path $Dir.FullName -Force -Recurse
Это сделано по причине того, что PowerShell не может удалить папки, на которые у пользователя нет прав, даже если оболочка запущена с повышенными административными правами. Проблема решается вызовом обычной командной строки с командой RD, которая не имеет указанной проблемы.
$CmdLine = "cmd /c RD /S /Q """ + $Dir.FullName + """" Invoke-Expression -command $CmdLine
Перед использованием скрипта на сервере нужно разрешить выполнение неподписанных сценариев командой
Set-ExecutionPolicy -ExecutionPolicy "RemoteSigned"
Проверить текущую политику выполнения сценариев можно командой
Get-ExecutionPolicy
Чтобы корректно удалять профили, нужно чтобы все сессии этих профилей были завершены и перемещаемые профили вернулись на файловый сервер, если это возможно. Форсировать завершение сессий и отправку профилей на файловый сервер можно перезагрузкой сервера. В планировщике заданий Windows нужно поставить 2 задачи:
- задачу на перезагрузку сервера раз в неделю перед началом рабочего дня;
- задачу на выполнение скрипта от имени системы с повышенными административными правами при загрузке сервера.
Запуск скрипта лучше осуществлять через командный файл
powershell.exe "%~DP0Remove-Profiles.ps1"
После выполнения сценария все профили, которые зависли на терминальном сервере будут стерты. А копии профилей с правильной конфигурацией останутся на файловом сервере. То есть при входе в терминальную сессию пользователь получит последнюю правильную копию своего профиля.
