Outlook, SharePoint, Office365 и Skype for Business позволяют использовать фотографию текущего залогиненого пользователя из Active Directory (Azure AD) в качестве аватары пользователя в своем интерфейсе. В этой статье мы покажем, как с помощью групповых политик и PowerShell использовать фотографию пользователя Active Directory в качестве рисунка профиля пользователя Windows 10, который отображается на экране приветствия, блокировки, в стартовом меню и т.д.
Наш скрипт будет работать следующим образом: при входе пользователя в систему, должен запускаться скрипт, который получает фото пользователя из атрибута thumbnailPhoto в Active Directory, сохранять файл изображения на диск и устанавливает этот файл в качестве аватарки профиля пользователя Windows. Решение должно одинаково работать на всех поддерживаемых клиентах: Windows 10 (8.1/7) и на RDSH северах с Windows Server 2016/2012 R2.
Импорт фотографий пользователей в Active Directory
В первую очередь нужно для пользователей AD установить фотографии, загрузив их в специальный атрибут thumbnailPhoto учетной записи. Вы можете установить фото пользователям с помощью сторонних программ, или с помощью модуля ActiveDirectory для Windows PowerShell (размер файла с фотографией должен быть не более 100 Кб и разрешением до 96×96 пикселей):
$photo = [byte[]](Get-Content C:\PS\divanov_photo.jpg -Encoding byte)
Set-ADUser divanov -Replace @{thumbnailPhoto=$photo}
Предоставляем пользователям права на смену иконки профиля
В Windows 10 информация об картинке аккаунта (путь к картинке, использующейся для профиля пользователя) хранится в системной ветке реестра HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users. Чтобы пользователи без прав администратора могли внести изменения, нужно предоставить им права на запись в этот раздел реестра.
- Проще всего раздать права на реестр через групповые политики. Для этого создайте новую политику и привяжите ее к OU с компьютерами пользователей;
- Затем перейдите в раздел Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Registry и создайте новый ключ реестра (Add key) с путем MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users;
- Затем на вкладке Security нужно предоставить право Full Control для всех пользователей домена (группа [DomainName]\Users) и нажмите ОК;
- В следующем диалоговом окне выберите Replace Existing permission on all sub keys with inheritable permissions, иначе у пользователей не будет прав на вложенные ветки реестра;
PowerShell скрипт получения фото пользователя из AD и установки иконки профиля Windows
Далее нам понадобится PowerShell скрипт, который должен получить фото текущего пользователя из Active Directory, сохранить его в jpg файл и установить его в качестве иконки профиля пользователя. Есть два варианта получения фото из AD: с помощью командлета Get-ADUser из модуля ActiveDirectory (этот модуль должен быть установлен на всех компьютерах через RSAT, или достаточно скопировать необходимые файлы модуля RSAT-AD-PowerShell без установки RSAT). Чтобы скрипт был универсальным и корректно работал в том числе на Windows 7, мы не будем использовать модуль RSAT-AD-PowerShell, а обратимся к AD через класс ADSISearcher.
Пример скрипта SetADPicture.ps1 для получения фото пользователя из AD и установки его в качестве аватары аккаунта Windows представлен ниже:
[CmdletBinding(SupportsShouldProcess=$true)]Param()
function Test-Null($InputObject) { return !([bool]$InputObject) }
$ADuser = ([ADSISearcher]"(&(objectCategory=User)(SAMAccountName=$env:username))").FindOne().Properties
$ADuser_photo = $ADuser.thumbnailphoto
$ADuser_sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
If ((Test-Null $ADuser_photo) -eq $false) {
$img_sizes = @(32, 40, 48, 96, 192, 200, 240, 448)
$img_mask = "Image{0}.jpg"
$img_base = "C:\Users\Public\AccountPictures"
$reg_base = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users\{0}"
$reg_key = [string]::format($reg_base, $ADuser_sid)
$reg_value_mask = "Image{0}"
If ((Test-Path -Path $reg_key) -eq $false) { New-Item -Path $reg_key }
Try {
ForEach ($size in $img_sizes) {
$dir = $img_base + "\" + $ADuser_sid
If ((Test-Path -Path $dir) -eq $false) { $(mkdir $dir).Attributes = "Hidden" }
$file_name = ([string]::format($img_mask, $size))
$path = $dir + "\" + $file_name
Write-Verbose " saving: $file_name"
$ADuser_photo | Set-Content -Path $path -Encoding Byte -Force
$name = [string]::format($reg_value_mask, $size)
$value = New-ItemProperty -Path $reg_key -Name $name -Value $path -Force
}
}
Catch {
Write-Error "Check permissions to files or registry."
}
}
Скрипт получает значение атрибута thumbnailphoto текущего пользователя из Active Directory AD и сохраняет фото в каталог C:\Users\Public\AccountPictures\{SID пользователя}. В каталоге будут содержаться графические файлы с разными разрешениями (от 32×32 до 448×448 пикселя) под разные форматы элементов интерфейса Windows 10: image32.jpg, image40.jpg и т.п.
Привязка фотографий к профилю пользователя осуществляется в ветке реестра HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users\{SID пользователя}.
Запуск PowerShell скрипта для привязки фото к профилю через GPO
Теперь нам нужно, чтобы скрипт SetADPicture.ps1 запускаться при входе пользователя в Windows. Проще всего это реализовать через логон скрипт группой политики.
Для этого в ранее созданной ранее политики в разделе User Configuration -> Policies -> Windows Settings -> Scripts (Logon/Logoff), создайте новый Logon скрипт, запускающий ваш PowerShell скрипт:
Исполняемый файл: %windir%\System32\WindowsPowerShell\v1.0\powershell.exe
Параметры скрипта: -Noninteractive -ExecutionPolicy Bypass -Noprofile -File %logonserver%\netlogon\script\SetADPicture.ps1
Осталось назначить политику на нужные OU с компьютерами, выполнить logoff и logon пользователя.

Для диагностики применения GPO на целевых компьютерах используйте утилиту gpresult и статью “Почему не применяется GPO?”.
После этого пользователю Windows 10 будет назначена аватарка из AD, и она начнет корректно отображаться в качестве рисунка учетной записи пользователя в стартовом меню, на экране входа в систему и других окнах. Инструкция по назначению фотографии профиля работает нормально и протестирована в Windows 10 LTSC (1809).
Фотография пользователя на экране приветствия просто здоровская штука! Все по полочкам разложили, отлично!
Вот только чтобы более менее качественное фото отображалось, нужно в AD грузить фото с разрешением не меньше 150×150 px. 96×96 смотрится куцо.
А у меня только папка создается AccountPictures, но она пустая… не пойму, в чем дело.
Если даже быть точнее: $path содержит в себе путь, включая файл.
и даже S-1… скрытая папка имеется в AccountPictures
но вот файл этот не сохраняется в папке.
$path
C:\ProgramData\AccountPictures\S-1-5-21-1127646421-3318506029-1329146387-3274\Image448.jpg
ХЭлп
Не очень понял причину, но скрипт таки отработал и фотки появились… Не понимаю этой странности.
Но спасибо, за статью!
А если у юзера нет фото в АД — что будет ? Или такие юзеры «игнорируются» ?
Игнорируются. В скрипте выполняется проверка на наличие данных в атрибуте thumbnailPhoto:
If ((Test-Null $ADuser_photo) -eq $false)
А на Windows 7 это точно работает? В реестре все создалось, в папке фото тоже все есть. Но аватарка не меняется.
Доброго времени суток. У меня то же возникла проблема на Win 7Скрипт отрабатывает, но фото не появляется, и папки programm Data нету. Можете подсказать как быть?
А на терминальном севрере (Windows 2016) работает сабж ??
Не пробовал. Теоретически схема рабочая для всех версий Windows.
Если получится — поделитесь результатом!
На 10 и 2012 и 2016 все работает, спасибо) Но вот в 2008 нет, папка с фотками создается, а вот в реестре такой ветки вообще нет… Хотелось бы и там, много пользователей по RDP работают на 2008. А так все отлично, написано просто и понятно, да и статей то кроме этой больше не нашел, так что за труды еще большое спасибо)
Да и на 7 тоже не работает, так же как на 208 нет ветки в реестре, если создаю руками ее, то вроде все подгружается но картинка все равно не отображается, может для 7 и 2008 где то в другое место надо указывать…
Здравствуйте. После применения политики со скриптом отваливается все приложения win10 вместе с пуском. Найти решение не смог. Иногда, в половине случаев, помогает только полная подмена ветки SOFTWARE реестра из RegBack. Перепробовал кучу способов из интернета. Версия вин10 не влияет. Сервер 2008. Нет ни у кого способа решения проблемы?
Удалось настроить смену аватар на Windows 7, правда не много другим путем.
1. https://msitpros.com/?p=1036
2. https://adusertile.codeplex.com/releases/view/80483 (рабочий файл)
Добрый день!
Скрипт на ПК отработал с ошибкой (см. ниже), а на контроллере домена все норм. Это нормально?
строка:23 знак:10
+ $value = New-ItemProperty -Path $reg_key -Name $name -Value $path -Fo …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (HKEY_LOCAL_MACH…1294222501-1794:String) [New-ItemProperty], SecurityException
+ FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShell.Commands.NewItemPropertyCommand
Применил политику на OU, перетащил туда и пользователя и ПК
Но папка C:\ProgramData\AccountPictures не создалась.
В gpresult /R показывает созданную политику
Как еще можно проверить где затык ?
На тестовом ноуте из папки sysvol/scripts запустил скрипт, он отработал фото появилось. Но автоматом что то не работает
фото под разные форматы: — как знать когда какой используется?
Добрый день. Данный метод еще работает в версия Windows 10 1903? У меня так и не получается вставить картинку пользователя в аватарку. Помогите пожалуйста если у кого получилось это сделать.
Забыл написать. Фотки в папке появляются, но в аве так и не высвечиваются.
в Windows 10 LTSC аватары пользователя появляются, но только после второй перезагрузки.
А билд какой ?
Билд 1903
Где-то в коде скрипта ошибка и он пытается писать в файловую систему при попытке записи в реестр.
Так что я выкинул из скрипта все, что не касается конвертирования картинок.
Запись в реестр, создание структуры каталогов доверил старому доброму VBS
Заработало ? Если да, то поделитесь решением пожалуйста.
Добавлена функция смены разрешения картинки ResizeImage
Добавлены условия try/catch для отладки (нужновырезать)
Function ResizeImage {
Param (
[Parameter(Mandatory = $True, HelpMessage = "image in byte")]
[ValidateNotNull()]
$imageSource,
[Parameter(Mandatory = $true, HelpMessage = "Параметр размер должен быть от 16 до 1000")]
[ValidateRange(16, 1000)]
$canvasSize,
[Parameter(Mandatory = $true, HelpMessage = "Параметр качества должен быть от 1 до 100")]
[ValidateRange(1, 100)]
$ImgQuality = 100
)
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$imageBytes = [byte[]]$imageSource
$ms = New-Object IO.MemoryStream($imageBytes, 0, $imageBytes.Length)
$ms.Write($imageBytes, 0, $imageBytes.Length);
$bmp = [System.Drawing.Image]::FromStream($ms, $true)
# Размер картинки после конвертации
$canvasWidth = $canvasSize
$canvasHeight = $canvasSize
# Задание качества картинки
$myEncoder = [System.Drawing.Imaging.Encoder]::Quality
$encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
$encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($myEncoder, $ImgQuality)
#Получаем тип картинки
$myImageCodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object { $_.MimeType -eq 'image/jpeg' }
# Высчитывание кратности
$ratioX = $canvasWidth / $bmp.Width;
$ratioY = $canvasHeight / $bmp.Height;
$ratio = $ratioY
if ($ratioX -le $ratioY) {
$ratio = $ratioX
}
# Создание пустой картинки
$newWidth = [int] ($bmp.Width * $ratio)
$newHeight = [int] ($bmp.Height * $ratio)
$bmpResized = New-Object System.Drawing.Bitmap($newWidth, $newHeight)
$graph = [System.Drawing.Graphics]::FromImage($bmpResized)
$graph.Clear([System.Drawing.Color]::White)
$graph.DrawImage($bmp, 0, 0 , $newWidth, $newHeight)
# Создание пустого потока
$ms = New-Object IO.MemoryStream
$bmpResized.Save($ms, $myImageCodecInfo, $($encoderParams))
# уборка
$bmpResized.Dispose()
$bmp.Dispose()
return $ms.ToArray()
}
$ADUserInfo = ([ADSISearcher]"(&(objectCategory=User)(SAMAccountName=$env:username))").FindOne().Properties
$ADUserInfo_sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
If ($ADUserInfo.thumbnailphoto) {
$img_sizes = @(32, 40, 48, 96, 192, 200, 240, 448)
$img_base = "C:\Users\Public\AccountPictures"
$reg_key = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users\$ADUserInfo_sid"
If ((Test-Path -Path $reg_key) -eq $false) { New-Item -Path $reg_key } { write-verbose "Reg key exist [$reg_key]" }
Try {
ForEach ($size in $img_sizes) {
$dir = $img_base + "\" + $ADUserInfo_sid
If ((Test-Path -Path $dir) -eq $false) { $(New-Item -ItemType directory -Path $dir).Attributes = "Hidden" }
$file_name = "Image$($size).jpg"
$path = $dir + "\" + $file_name
Write-Verbose " Crete file: [$file_name]"
try {
ResizeImage -imageSource $($ADUserInfo.thumbnailphoto) -canvasSize $size -ImgQuality 100 | Set-Content -Path $path -Encoding Byte -Force -ErrorAction Stop
Write-Verbose " File saved: [$file_name]"
}
catch {
If (Test-Path -Path $path) {
Write-Warning "File exist [$path]"
}
else {
Write-Warning "File not exist [$path]"
}
}
$name = "Image$size"
try {
$null = New-ItemProperty -Path $reg_key -Name $name -Value $path -Force -ErrorAction Stop
}
catch {
Write-Warning "Reg key edit error [$reg_key] [$name]"
}
}
}
Catch {
Write-Error "Check permissions to files or registry."
}
}