No matter where I work, I always load a headshot picture into my profile or email. I think it adds a personal touch to technology as people know who is helping them. After a short amount of time, people recognize me in person because of this. This would lead to conversations where someone would know my name but I would have no idea who they were. Eventually, they would say something about me fixing their problem and I would go, “oh – you’re the lady with that printer” or something like that.
In an effort to reduce that social awkwardness*, I needed a way to import user photos into Outlook. The thumbnailPhoto attribute is responsible for the user headshot that appears in Outlook or Skype for Business. It can even be synced to the local machine Windows account photo. With that, I just needed a picture for each staff member that I could match to AD. Most organizations have a staff directory and someone has probably taken the time to match and upload a photo for each employee.
The following script is designed to take pictures from an online staff directory and import them into the matching Active Directory user’s thumbnail attribute. If you use Blackboard as your website host, you might not need to modify anything beyond the last page number (if your directory has multiple pages), the URL, and the searchbase value. You made need to use the Network tab in Chrome’s developer tools to see where any javascript links end up.
If your staff directory is not ran off of Blackboard, you can still use this script. Using your browser developer tools, look at the structure of your directory and the picture. Ideally, the picture would have first and last name values attached to it. You would need to modify the value names in the script below.
This script does use another tool to convert pictures into an AD Friendly format. Download and extract the contents of the ADPhotos folder into C:\Users\Public\Staff\ . Your file/folder structure should look like this (extra files/folders are fine):
If you have any issues implementing this script, leave a comment or email me (include your staff directory website). I will try to point you in the right direction. As always, be sure to had a few pause statements and -whatif parameters to test the script first.
*The only way that I can remember to spell awkward is to think about how that K feels when it is squished between those two W‘s. It must feel, well, awkward.
#Extra script files required: https://deployhappiness.com/wp-content/uploads/2015/01/ADPhotos.zip #Enter the last page number for your staff directory [int]$LastPage = 30 #Enter the staff directory URL with the page number value removed $URL = "https://www.WEBSITE.com//cms/UserControls/ModuleView/ModuleViewRendererWrapper.aspx?DomainID=&PageID=&ModuleInstanceID=&PageModuleInstanceID=&Tag=&PageNumber=" #Searchbase for Get-ADUser. Picture Name to ADUser Name matching will only be done within this searchbase. $SearchBase = "OU=Staff,OU=DOMAIN,OU=local" #This folder is where pictures are downloaded to.GALBatchConvert.ps1 will convert pictures from this folder and save them to $OutputFolder $InputFolder = "C:\Users\Public\staff\Downloaded\" #This folder is where pictures are stored after being converted to an AD friendly format. These will be the pictures that are imported. $OutputFolder = "C:\Users\Public\staff\Converted\" Set-Location "C:\Users\Public\Staff\" $PageNumber = 1 $Date = Get-Date -Format o | foreach {$_ -replace ":", "."} #To remove valid errors when Get-ADUser failes, unremark the line below. Note that this will silence all errors though. #$ErrorActionPreference = "silentlycontinue" while ($PageNumber -le $LastPage){ $URI = $URL+$PageNumber $StaffPictureWebsite = Invoke-WebRequest -Uri $URI -SessionVariable StaffPictureWebsite #Downloads all pictures that have the data-firstname attribute set and saves them as firstname.lastname.jpg in the $Inputfolder $StaffPictures = $StaffPictureWebsite.Images | where data-firstname -NE $Null foreach ($StaffPicture in $StaffPictures){ $URI = "https://www.wayne.k12.ga.us/" + $StaffPicture.src $StaffPictureName = $StaffPicture.'data-firstname' + '.' + $StaffPicture.'data-lastname' + '.jpg' Invoke-WebRequest -Uri $URI -OutFile $InputFolder$StaffPictureName } #Converts pictures from $InputFolder into an AD friendly format (96x96; 10Kb or less in size). Saves them to $Outputfolder #If your files are greater than 10Kb after being converted, reduce the $Quality variable in GalBatchConvert.ps1 #GalBatchConvert.ps1, convert.exe, and vcomp100.dll should be in the folder specified by the Set-Location line above. .\GALBatchConvert.ps1 -InputFolder $InputFolder -OutputFolder $OutPutFolder #Gets name of pictures in $Outputfolder and attempts to match them to a user in AD. #First attempt is by firstname.lastname (name of file). #Second attempt is by proxyaddress (name of file). #Final attempt is by dividing the file name into two parts (first and last names) - taking the first letter of the first part and joining it to the second part (first initial+lastname) #Any files that match a user will be deleted after one of two outcomes. If the user has a photo already, no import is done/file is deleted. If the user does not have a photo, the import is done/file is deleted. #Any files not matched to a user is left for you to review at the end of the process. These can be found in the $Outputfolder $PictureDirectory = Get-ChildItem $OutputFolder | where name -Like *.jpg foreach ($Picture in $PictureDirectory){ $PictureName = $Picture.Name $Name = (($Picture.Name).tostring()).trimend(".jpg") write-host "" write-host Current user: $Name write-host Searching for username with FirstName.LastName - $Name -foregroundcolor yellow $ADuser = Get-ADUser -identity $Name -ErrorAction SilentlyContinue if ($? -eq $true){ $ThumbNail = Get-ADUser -Identity $ADuser -Properties thumbnailPhoto | select -ExpandProperty thumbnailPhoto if(($ThumbNail).count -ne 0){ write-host thumbnailPhoto already set for $Name - Skipping to next user. -ForegroundColor Green Remove-Item -Path $Picture.FullName -Force | out-file ".\log$date.txt" -Append continue } else{ write-host No thumbnail photo set for $Name $PictureContent = [byte[]](Get-Content .\$OutPutFolder$PictureName -Encoding byte) Set-ADUser -Identity $ADUser.SamAccountName -Add @{thumbnailPhoto=$PictureContent} | out-file ".\log$date.txt" -Append if($? -eq $True){write-host "thumbnailPhoto set for "$Name -ForegroundColor Green} } } else{ write-host Searching for proxyAddress with FirstName.LastName - $Name -foregroundcolor yellow $ADuser = Get-ADUser -Filter * -Searchbase $SearchBase -Properties proxyaddresses | where proxyaddresses -match $Name if ($ADuser -eq $Null){ $FirstInitalLastName = ($Name.Split(".")[0]).substring(0,1) + $Name.Split(".")[1] write-host No proxyAddress found. Searching for username with FirstInitial+LastName - $FirstInitalLastName -ForegroundColor Yellow $ADuser = Get-ADUser -Identity $FirstInitalLastName -Searchbase $SearchBase if ($ADuser -eq $Null){ Write-Host No matching user could be found for $Name or $FirstInitalLastName. Picture will be saved for review. Skipping to next picture. -ForegroundColor Red Continue } } if ($ADuser.Count -gt 1){ write-host More than one matching user found. Picture will be saved for review. Skipping to next picture. -ForegroundColor Red continue } Write-Host Found AD User $ADuser.SamAccountName for $Name $ThumbNail = Get-ADUser -Identity $ADuser -Properties thumbnailPhoto | select -ExpandProperty thumbnailPhoto if(($ThumbNail).count -ne 0){ write-host thumbnailphoto already set for $Name - Skipping to next user. -ForegroundColor Green Remove-Item -Path $Picture.FullName -Force | out-file ".\log$date.txt" -Append continue } else{ write-host No thumbnail photo set for $Name $PictureContent = [byte[]](Get-Content $OutPutFolder$PictureName -Encoding byte) Set-ADUser -Identity $ADuser.SamAccountName -Add @{thumbnailPhoto=$PictureContent} | out-file ".\log$date.txt" -Append if($? -eq $True){write-host "thumbnailPhoto set for "$Name -ForegroundColor Green} } } Remove-Item -Path $Picture.FullName -Force | out-file ".\log$date.txt" -Append } #And we are done with the first page! We rest a second (because that was hard) and remove the files from the $InputFolder. We increase the $PageNumber value and start back at the top loop. Write-host Finished with $Pagenumber. sleep -Seconds 1 Remove-Item -Path $InputFolder\ -include *.jpg -Force -Recurse | out-file ".\log$date.txt" -Append $PageNumber = $PageNumber + 1 }
I use a freeware application from Code Two to set the user pictures: https://www.codetwo.com/freeware/active-directory-photos/
Wow! That is quite the script! Hoping that I can get it to work in my domain.
Also – I like the comments.
Thanks Ryan! 🙂