Upload user photo to AD

I wrote a series of Powershell functions and scripts to perform a set of tasks. The new hires get their photo taken, and those photos need to be applied to the various systems that store user photos. More will be added over time, but now, I have functions that upload to Active Directory, Azure AD, Exchange, and a SQL Server database.

As you might be aware, most of those systems only accept images up to a certain size. So I ripped off a function that resizes an image. I wrote a wrapper to shrink an image a little at a time until its size is smaller than the indicated value.

Check out the whole repository at https://gitlab.com/bgstack15/former-gists/tree/master/userphotos.

The basic task is to upload an image to Active Directory. A workflow in a Sharepoint instance handles the image uploads from users and the approval by a security officer, but then a script downloads all the photos Apply-Photos-From-SharePoint.ps1. The images are named according to the email address of the user already, so they’re just downloaded wholesale.

Once the files are on the local filesystem, that script loops through them and uploads them.

ForEach ($file in Get-ChildItem $Outdir | Where-Object { -Not ( $_.Name -Match ".*(_[0-9]{2}|[0-9]{6})\.[^.]{1,6}" ) } )
{
    $null = Process-User-Photo -File $file
}

In the library, the function Process-User-Photo extracts the user in question based on the name and calls the wrapper function for uploading to all services.

		$Result = Set-Photo-All -User $samaccountname -Filename $file.Fullname
		if ($Result -eq 0)
		{
			Log "Success: ${file}"
			Move-With-Rename -Path $file.Fullname -Destination "$MoveToOutdir\"
		}

And Set-Photo-All is pretty simple. It will return an integer which represents the number of failures of the individual set-photo functions.

# Set-Photo-All -User $User -Filename $Filename
Function Set-Photo-All {
	Param(
		[Parameter(Mandatory=$true)] $User,
		[Parameter(Mandatory=$true)] $Filename
	)
	$Result = 0
	$Result -= Set-Photo-AD -User $User -Filename $Filename
	# AzureAD synchronizes from on-prem AD approximately every 15 minutes.
	#$Result -= Set-Photo-AzureAD -User $User -Filename $Filename
	$Result -= Set-Photo-Outlook -User $User -Filename $Filename
	$Result -= Set-Photo-SQLServer -User $User -Filename $Filename
	return $Result
}

Uploading to AD is actually really easy.

# Set-Photo-AD -User $User -Filename $Filename
Function Set-Photo-AD {
	Param(
		[Parameter(Mandatory=$true)] $User,
		[Parameter(Mandatory=$true)] $Filename
	)
	$Result = -1
	$newfile = Get-Photo-Below-Size -Filename $filename -MaxSize 100000
	$photo = [byte[]](Get-Content $newfile -Encoding byte)
	Try
	{
		Get-ADUser $User | Set-ADUser -Replace @{thumbnailPhoto=$photo}
		If ($newfile -ne $Filename) { Remove-Item -Path $newfile }
		Log "Set AD photo for ${User} to ${newfile}"
		$Result = 0
	}
	Catch
	{
		Write-Error $_
	}
	Remove-Variable newfile
	return $Result
}

Of course there’s a getter function as well, for each service.

# Get-Photo-AD -User $user -Filename $filename
Function Get-Photo-AD {
	Param (
		[Parameter(Mandatory=$True)] $user,
		[Parameter(Mandatory=$True)] $filename
	)
	# save photo down from AD to inspect it
	# https://devblogs.microsoft.com/scripting/weekend-scripter-exporting-and-importing-photos-in-active-directory/
	$user = get-aduser $user -properties thumbnailphoto
	[System.Io.File]::WriteAllBytes($filename,$user.thumbnailphoto)
}

So the whole library is modular. You can dot-source the whole thing and run just individual statements ad-hoc, or use the library for a wholistic solution which is why I needed it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.