Uploading pictures from SharePoint to Active Directory attribute thumbnailPhoto


My customer recently had some issues exporting Picture from SharePoint My Site to Active Directory using the ThumbnailPhoto attribute.  What was happening is that User Profile Application was not exporting all pictures and Full imports were deleting all pictures that were already in Active Directory.

After some research I found a bug in SharePoint that had already been fixed in the Dec 2011 Cumulative Update, but during research and testing we played with scripting a solution just in case I was wrong (Working on a deadline that had already slipped)

Here is the script that I created it's very rough and needs error checking and as well as possible optimization but it was written with the hope to not be needed, as well there are some caveats that I want to make you aware of

  1. This needs to be run on Windows 2008 R2 server so that I can install the Active Directory Module.  You could install it yourself and change a few lines to get around that thought if you wanted.
  2. I download all the pictures from the internet to the hardrive so make sure you have enough room to deal with that.  I suggest estimating each picture at 100KB, as that is the max size for the attribute thumbnailPhoto.
  3. I use 'GetUserProfileByIndex()' to create my list of profiles to download the picture from it was quick to implement but it only includes those profiles that have a My Site.  This was fine for me, but depending on your implementation that may not be adequate.   I hope to change this in the future.
  4. The account that you run the script with needs write permission to the accounts that your editing.
  5. The account $RunAsAccountName needs access to the user profile service.

With all that being said here is my script, please take it and make it your own.  Remember to test it first and that I'm not responsible for any problems you may have, this is just a sample.  With that being said I would love to hear ofany issues or improvements you may have.

#Import module

$Modules=Get-Module

if ($Modules-notcontains"ActiveDirectory")

{

Start-Process-FilePathocsetup.exe-ArgumentList"ActiveDirectory-PowerShell"-Wait

import-moduleActiveDirectory

}

# Set Variables

$FilePath=$env:temp

$SUrl="https://weasp03/_vti_bin/userprofileservice.asmx"

$WebApp=“https://weasp03/”

$Path=“my/”

$Library=“User%20Photos/Profile%20Pictures/”

$Domain= (Get-ADDomain).NetBIOSName

$SearchTopLevelOU= (Get-ADDomain).DistinguishedName

$RunAsAccountName="contoso\farm3-admin"

$RunAsAccountPassword=P@ssword1

# DO NOT EDIT THESE LINES

$SecureRunAsAccount=ConvertTo-SecureString$RunAsAccountPassword-AsPlainText-Force

$Credential=new-object-typenameSystem.Management.Automation.PSCredential-argumentlist$RunAsAccountName,$SecureRunAsAccount

functionDownloadPictures

{

param($Credential,$FilePath,$SUrl)

[system.reflection.assembly]::LoadWithPartialName("System.Web") |Out-Null

if($FilePath.EndsWith("\") -eq$false)

{

$FilePath=$FilePath+"\"

}

$Service=New-WebServiceProxy-Uri$SUrl-NameSpaceUserProfileService-Credential$Credential

#Create WebRequest

$WebRequest=new-objectSystem.Net.WebClient

$WebRequest.Credentials =$Credential.GetNetworkCredential()

$ProfileCount=$Service.GetUserProfileCount()

$NextIndex=0

for($ProfileLoop=0;$ProfileLoop-lt$ProfileCount;$ProfileLoop++)

{

$UPD=$Service.GetUserProfileByIndex($NextIndex)

$Prop=$UPD.UserProfile |Where-Object { $_.Name -eq"AccountName" }

$AccountName=$Prop.Values[0].Value

$Prop=$UPD.UserProfile |Where-Object { $_.Name -eq"PictureURL" }

$PictureURL=$Prop.Values[0].Value

if($PictureURL-ne$null)

{

$FileName=$FilePath+$AccountName.SubString($AccountName.LastIndexOf("\")+1) +$PictureUrl.SubString($PictureUrl.LastIndexOf("."))

$WebRequest.DownloadFile($PictureUrl,$FileName)

}

$NextIndex=$UPD.NextValue

}

}

if ((gwmiwin32_OperatingSystem).Version -like"6.1.*")

{

DownloadPictures-Credential$Credential-FilePath$FilePath-SUrl$SUr

$Users=Get-ADUser–Filter*-SearchBase$SearchTopLevelOU

ForEach($Userin$Users)

{

$FileName=$User.SamAccountName

[byte[]]$photo=Get-Content"$FilePath\$FileName.jpg"-Encodingbyte-eaSilentlyContinue

if ($Photo-ne$null)

{

Get-AdUser-identity$User.SamAccountName |Set-ADUser-Replace @{thumbnailPhoto=$photo}

Write-Output"Uploaded photo for $FileName"

}

}

}

Else

{

Write-Output"Script needs to be run on Windows 7/Windows 2008R2"

}