I work in I.T and am therefore both exciting and dynamic, this much is given. Often this exciting dynamism – henceforth known as excitamism – takes the form of such thrilling activities as massive OS rollouts, cluster building or VOIP tinkering. Sometimes it takes the form of adding a generic photo to every user account in AD.

Every user account. All of them. The mail-enabled ones anyway, there’s no point with the others because they don’t appear in the address book. Amirite?

It is at times like these that you think to yourself “but I don’t want to do that all by hand, I am lazy” and by summoning the full power of your brain you achieve the impossible. At the very least you achieve a mackled together PowerShell script that does the job for you. Then you run it on a schedule so that you never have to do it again. EXCITAMISM!

#If I could be bothered, I'd hack this a little more to add error some handling and a message when no results were returned.
#I can't though, because I am. There's some annotation though. Let's hear a big hurrah for jerry-rigging.

#import PowerShell AD Module
Import-Module ActiveDirectory
#set search root as required eg: OU=Users,DC=your,DC=Domain
$searchRoot = OU=Users,DC=your,DC=Domain"
#set default image source for your user profiles 96x96px jpg, gif, whatever
$defaultImageSrc = "C:\Tools\Powershell\Resources\default.jpg"

#wait function just for the sake of it
function wait{
Write-host -ForegroundColor Green "`nPress any key to continue ..."
$HOST.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") | OUT-NULL
$HOST.UI.RawUI.Flushinputbuffer()
}

# exit the script
function quit {
exit
}

#queries ad for mail enabled users with no profile photo set
function setPhoto{
Write-host -ForegroundColor Green "Running"
$users = GET-ADUSER -filter * -SearchBase $searchRoot -properties ThumbnailPhoto,Mail | Where { $_.ThumbnailPhoto -eq $NULL -and $_.mail -ne $NULL}
#loops through the returned results and sets the thumbnail photo
ForEach($user in $users)
{
"Setting photo for $($user.name)"
#Old method removed to replace the requirement for Exchange Snap-In being loaded
#Import-RecipientDataProperty -Identity $user.distinguishedName -Picture -FileData ([Byte[]]$(Get-Content -Path $defaultImageSrc -Encoding Byte -ReadCount 0))
Set-ADUser $user.distinguishedName -Replace @{thumbnailPhoto=([byte[]](Get-Content $defaultImageSrc -Encoding byte -ReadCount 0))}
}
Write-Host -ForegroundColor Green "Done"
wait
}

#queries ad for mail enabled users and returns them in a list
function noPhoto{
Write-host -ForegroundColor Green "Mail enabled users with no photo set"
GET-ADUSER -filter * -SearchBase $searchRoot -properties ThumbnailPhoto,Mail | Where { $_.ThumbnailPhoto -eq $NULL -and $_.mail -ne $NULL} | Select Name | Sort-Object Name
Write-Host -ForegroundColor Green "Done"
wait
}

#menu loop
do {
[int]$xMenuChoiceA = 0
while ( $xMenuChoiceA -lt 1 -or $xMenuChoiceA -gt 3 ){
cls
Write-host "AD Photo Tool`n"
Write-host -ForegroundColor Cyan "1. List users with no photo"
Write-host -ForegroundColor Cyan "2. Set default photo"
Write-host -ForegroundColor DarkCyan "3. Quit and exit"
[Int]$xMenuChoiceA = read-host "`nPlease enter an option 1 to 3" }
Switch( $xMenuChoiceA ){
1{cls | noPhoto}
2{cls | setPhoto}
default{cls | quit}
}
} while ( $userMenuChoice -ne 3 )

Run at your own risk, no support or anything else is implied. Blah, blah, blah. I’d credit the various people I bodged this together from if I could remember who they were. Don’t come crying to me. It’s all fun and games until someone loses and eye and so on.