Link to original post: https://adamsorenson.com/user-profile-picture-import-with-active-directory-import/
A new year, blog home, & version of the picture importer
I have just completed a migration to my new blog home here. This platform will give us a bit more flexibility with design and such. I have been working a many bugs that have been plaguing the profile picture import. I think I have a handle on the majority of the outstanding issues. The major bug we had was the terrible performance for larger pictures. This is now fixed since we don’t need to reset the variable. We are still using Active Directory Import(ADI) and able to do incremental.
New variable
There is one new variable to assist with the “LDAP Server Unavailable” issue. $DCorDomainName(line 20)
is set for a resolvable domain name(Netbios or FQDN) or a Domain Controller.
XML file will auto create
New logic in the script will create the DNLookup if it’s not present. There was another issue where existing users in AD would fail since the sAMAccountName property is not included with incremental syncs. This is resolved by doing a lookup by the DN and add them into the DNLookup.xml.
Excellent work. Thanks very much Adam for your efforts!
Thanks for a great script! I have a few thoughts / questions:
1) I suppose the script can handle being scheduled repeatedly (I was thinking once a week, using Task Scheduler)? And will it then always do a full import, re-importing already imported photos? But maybe a full import every time is the only feasible way to do it, in case a user has changed their picture…
2) It’s the $LDAPFilter that determines which AD-users should be processed, right? I’m not a script guru, but I tried to see if there’s logic for checking which users are actually imported to the UPSA already, and just querying the AD for images for those users?
3) We have several UPSA:s, how do I direct the script to run against a specific one? Is it merely by setting $site to the correct My site host in question?
4) Are there any “technical gains” in enabling $write2disk, or is it just for the convenience to be able to see the imported images?
Thanks for any insights! 🙂
Glad you’re able find some good usage for it.
1.) I have a blog post up on how to set this up as a task. — SharePoint – Scheduling the Profile Picture Import Script
This is the best way to schedule it. Since the script uses DirSync, this will create a cookie.bin file. The first time it runs it will be full pull from AD but will be incremental after that.
2.) The default LDAP filter I put in the script is to find users that have a value in thumbnailPhoto and is also not disabled. After we pull these in, we only upload pictures that are in the UPA.
3.) The $site should be the mysite host. I don’t know the reasoning behind having multiple UPAs but this will pull the default UPA that the site is consuming from. Also $site will the site collection we will be uploading the photos to.
4.) This will cause a slight perf loss. I put it in there for troubleshooting or anything else you’d like to do with the pictures.
–Adam
Thanks a lot for your reply Adam!
Great post, I had good timing with my scheduling question. 🙂 As the task should be run as the UPSA sync account, I should then obviously set $UseDifferentSvcAccount to “$false”?
The script works well when I execute it manually, but I do have some problems, most likely with permissions, when running it as the sync account. It’s “Unable to get UserPhotos” (even though the folder exists) so I need to figure that one out…
Oh, about multiple UPSA – we are basically running one environment for multiple customers, so we’re running multiple UPSA to get airtight separation.
/W
It works also as a scheduled task now – I must’ve been too tired when giving the sync account SPShellAdmin permissions the first time around, I had given permissions to the wrong account… X-)
Thanks again, you rock! 🙂
Hi Adam,
I used your script to import thumbnail photos to SharePoint and it works perfect. Only thing i noticed is the low resolution of the photos. Thumbnailphoto has 96x96pixel limitation and that when comes to sharepoint my profile picture, it looks blurred. Is there any work around for this?
Thanks
Anina
Hi Anina,
I’m glad the script is working for you.
The quality of the picture is based on what is in Active Directory’s thumbnailphoto value. This is limited at 100 KB. SharePoint will create 3 versions of picture – small, medium, large.
Small -> username_SThumb.jpg
Medium -> username_MThumb.jpg
Large -> username_LThumb.jpg
You can run the script with $write2disk = $true to see what quality is coming from AD.
am getting the same issue the resolution is bad even with write2disk set to true, the file size doesnt exceed 2 KB on disk, is there a workaround for this
The resolution/size of the image is limited by what it is in AD. There would have to be a higher quality image stored in AD.
I work for a Non for Profit organization and we cannot invest on a new VM to setup MIM 2016 and would really want to get he User photos from AD thumbnail attribute over to our local SharePoint site.
Can anyone help me out with all steps from start to finish as I copied and pasted the script as is with changing the domain name and other attributes particular to my environment, but I am not sure what are the pre requisites to be setup before running the powershell script on the VM running SharePoint server 2016 as I realized just running the .ps script and changing attributes within the script failed for me.
There is a log file that is generated. Take a look in there to see if you setup the script correctly.
Hi Adam,
I’m running this script. It is working fine and uploading pictures. But I don’t see 3 sizes get uploaded. Does the script upload 3 sizes? I see the filename is partitionID_ user profileID.jpg, so I changed to the format in the mysite settings “username”. Now it is uploading with usename.jpg format, is this correct way of doing it and also, how to upload 3 sizes?
Hi Adam, my previous comment is not clear. I changed the filename in the script to follow the format in the mysite site name format which is username.jpg. (I didn’t change the format in the mysite settings)
The last line of the script should be the one that creates the 3 thumbnails.
Update-SPProfilePhotoStore -MySiteHostLocation $site -CreateThumbnailsForImportedPhotos $true
Try running this outside the script to see if it’s failing.
Adam, thanks for the reply. I missed your reply before.
I tried running with partition id , it is saving the picture in picture store with that partition id string, but no thumbnail pictures are created.
I ran this command also outside the script, it didn’t give me any error. It ran.
Update-SPProfilePhotoStore -MySiteHostLocation $site -CreateThumbnailsForImportedPhotos $true
Have couple of questions.
1.Does the partition ID have to be changed in the script?
2.After running the above update command when will the thumbnail pictures be generated?
Adam,
Creation of thumbnail pictures is working for me. The issue was I had 2 User profile service applications and the one associated with my site is different. I removed the other UPSA and pointed the mysite to correct UPS, it is now working. Thanks.
Pingback: User Profile Picture Import with Active Directory Import(Dirsync) - Adventures of SharePoint OnPrem
Hi,
first of all thanks for providing this script for importing pictures.
When the photo in AD is changed for an already imported user, will a re-run of the script update the profile picture in SharePoint, too?
This script will update pictures from AD incrementally. The first time the script is ran, cookie.bin is created. To run a full, delete cookie.bin.
The script does not seem to be available any longer. Can you post it here?
Hi Rick,
I’ve updated the link to Github. Looks like my scripts were part of the purge of Technet Gallery.
Thanks,
Adam
Hi Adam,
This script is failing for me after the line
$sam=Byte2DArrayToString -attr $dsam
I get:
Failed to create XML file
Cannot index into a null array.
If I delete the cookie file and run it works fiine.
Any thoughts what is coming back null?
There should be a dnlookup.xml file that is created as well. Do you see that file being created?
Hi Adam,
There is a DNlookup.xml, but it is blank. That blank DNlookup.xml is dated 7/1, which is the last time there was a new user to update. Since 7/1, the log shows:
Trying to get the Profile Pictures Folder
Successfully loaded the Profile Pictures
New upload started at 07/09/2021 22:31:17 for 0 users
Summary: Upload completed at 07/09/2021 22:31:17(took 00:00:00.0156294). 0 users imported from AD. 0 errors. 0 user photos successfully uploaded.
Hey Adam, I’m having an issue with the script, after running the script I get the message below in the out.log file. but these profile is in our User Profile Service. So I’m not sure why it is telling us it can’t find the user.
Also It is not downloading the pictures locally even when I set
$write2disk = $true.
Trying to get the Profile Pictures Folder
Successfully loaded the Profile Pictures
New upload started at 01/03/2022 11:50:39 for 106 users
Could not find User Profile for i:0e.t|pingsts|******
Could not find User Profile for i:0e.t|pingsts|******
Could not find User Profile for i:0e.t|pingsts|******
Could not find User Profile for i:0e.t|pingsts|******
we are using our dedicated AD sync account that has rights, and I’m running the script from the server running User Profile Services.
Thanks for your help
HI Jason,
This entry means we didn’t find a user profile that matched that name.
The line we’re running this this:
$UserProfile = $pm.GetUserProfile($username)
Check in the User Profile service application to see if you have those user profiles sync’d with AD in that format of i:0e.t|pingsts|******
Here is a test lines to see if you have the profiles and the account running the script doesn’t have permissions to the UPA:
Change these two lines
$site = Get-SpSite http://MySiteHostURL
$username = “i:0e.t|pingsts|******”
$context = Get-SPServiceContext($site)
$pm = new-object Microsoft.Office.Server.UserProfiles.UserProfileManager($context, $true)
$pm.GetUserProfile($username)
This may come back as access denied which would need to add that account to the UPA in central admin as documented here: https://adamsorenson.com/sharepoint-scheduling-the-profile-picture-import-script/
Adam, thank you for your reply
It turns out my User Profile service was not working as expected, Once I deleted and recreated the UPSA your script worked great. I will add that I had to give sharepoint permissions to my normal sync account that had previously only rights to active Directory. I gave it full control permissions of the UPSA service, made it shelladmin and gave the account full control of our MySiteHostURL. Adam thanks again for your post, this script avoids us from using MIM just for pictures.
Hi Jason,
First off thanks for this great script.
I have no issues when running the script manually with the “$UseDifferentSvcAccount = $true”. But I’ve gone through the steps in your other blog post to give the account the needed permission, and when I run it as a scheduled task I get the following. It’ s not clear what the error is. Do you have any ideas?
Trying to get the Profile Pictures Folder
Successfully loaded the Profile Pictures
New upload started at 02/02/2022 01:00:36 for 1 users
Uploading xDOMAIN\xUSER1
xDOMAIN\xUSER1 did not upload
Summary: Upload completed at 02/02/2022 01:00:37(took 00:00:01.2969085). 1 users imported from AD. 1 errors. 0 user photos successfully uploaded.
Hi Christian,
$UseDifferentSvcAccount will not work with scheduling the script. This will require storing credentials in the script itself which I did not intend on doing. You could modify the script to take a secure string. I’d advise looking at these methods if this is a requirement: https://social.technet.microsoft.com/wiki/contents/articles/4546.working-with-passwords-secure-strings-and-credentials-in-windows-powershell.aspx
Sorry if I wasn’t clear. When I run the script with UseDifferentSvcAccount using account “xyz” it works. When use that xyz account as the schedule task (and with the script set UseDifferentSvcAccount $false) I get the above issue.
Basically I can run the script using the account that I’m scheduling it with but only when it’s running as the schedule do I get that odd error.
When using $UseDifferentSvcAccount, this will use a different account(xyz) to import the pictures from AD. The rest of the script will run in context of the user that is running PowerShell.exe. That account will need access to the UPA and the Content Database(Shell access).
To fix this issue, give “xyz” account access to the Content Database that has the My Site Host Site Collection.
$site = get-spsite “http://mysitehostURL”
Add-SPShellAdmin -UserName contoso\xyz -database $site.ContentDatabase
https://adamsorenson.com/sharepoint-scheduling-the-profile-picture-import-script/
Hi Adam,
thanks for the script it works well except the quality of the pictures :/ The user saved self from his outlook profile and it has a normal size not the 2-7kb what we can extract from the AD with help of your script.
Is there any chance to get better quality?
The quality/size of the picture is what is stored in Active Directory. There is not a way to improve the quality unless you put a better picture in Active Directory.
The script is working good, but I have one question related to re-add of the user profileds with a different account. We have one user with domain\user1 userid and that user got terminated an year back and that user should have been removed after a month or so of the termination, but got re-hired recently with a different userid. The script is not updating the picture, giving error that domain\user1 not found. Somehow it is associating the old userid with the new user.
I’d delete the Dnlookup.xml and cookie.bin then run the script. This will kick off a full picture sync.
The script is not automatically creating the DNS Lookup xml. Is there a copy of that file around that I can use? If I create a bank xml file with that work?
Make sure the $Location has a valid directory set.
Hi Adam,
Thx a lot for this script.
I have an error when i launch it about “/User Photos/Profile Pictures” URL.
It’s about this part :
“Trying to get the Profile Pictures Folder”| out-file $log -Append -noclobber
$site.RootWeb.GetFolder(“User Photos/Profile Pictures”)
$PhotoFolder = $site.RootWeb.GetFolder(“User Photos/Profile Pictures”)
The error said: Exception calling “Add” with “1” argument(s): “(null) « User Photos/Profile Pictures » introuvable.”
introuvable = not found (i’m on french Windows and french Sharepoint install so maybe tthe error comes from that the Picture profil library path doesn’t have the same name in French?)
Good catch. That path would need to fit your environment’s language.