How to display Active Directory stored user account pictures in Windows?

Posted by on Aug 12, 2011 in Active Directory, VBScript | 7 comments

This topic is little more complex and we’ll need different steps to accomplish this feature.
First at all you need the pictures for your user objects in the directory. You can use ADSI Edit, Powershell or 3rd party software to put pictures in AD. My blog post “How to save a user picture in Active Directory with vbScript?” will do this for you using vbScript.
Second you’ll need a small application that sets a picture on your harddrive as the user account picture. I tested this only with Windows 7 – so there is no guarantee that this works with other versions too. Why an application? Because there is no documented way of setting an individual user account picture programmatically in vbScript – neither via registry nor via file system.
My blog post “How to set the Windows 7 user account picture programmatically?” covers that small application.
Now that we have the pictures in Active Directory and developed a small application that sets an image file as user account picture we just need one more step between both. We need a vbScript that runs at logon, loads the picture from AD, puts it on the disk and calls our application. Here we go:

Function LoadPictureFromAD(szADsPath, szSaveFileName)
	Dim objUser, bytesRead, adoStreamWrite
	Const adTypeBinary = 1, adSaveCreateOverWrite = 2
 
	Set objUser = GetObject(szADsPath)
	bytesRead = objUser.Get("thumbnailPhoto")
	
	Set adoStreamWrite = CreateObject("ADODB.Stream")
	adoStreamWrite.Type = adTypeBinary
	adoStreamWrite.Open
	adoStreamWrite.Write(bytesRead)
	adoStreamWrite.SaveToFile szSaveFileName, adSaveCreateOverWrite
	adoStreamWrite.Close
End Function

Set wshShell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")

workingdir = Replace(wscript.scriptfullname, Wscript.scriptname, "")

Set wshNetwork = WScript.CreateObject("WScript.Network")
username = wshNetwork.UserDomain  & "\" & wshNetwork.UserName
Set objSysInfo = CreateObject("ADSystemInfo")
strUserName = objSysInfo.UserName
dn = "LDAP://" & strUserName

path = wshShell.ExpandEnvironmentStrings("%temp%") & "\"
filename = path & "uap.jpg"

LoadPictureFromAD dn, filename
wshshell.run workingdir & "useraccountpicture.exe " & username & " " & filename, 0, true

This script contains the function LoadPictureFromAD which expects the user’s distinguished name and a filename where the resulting picture will be saved to. Inside the function we connect to AD, get the user’s object, read the attribute thumbnailPhoto, copy it to a previously created stream object and save it in a file identified by szSaveFileName.
The script itself assumes that the useraccountpicture.exe application resists in the same location as the script. So we set the working directory to the scripts location. After that we need the user’s name, it’s domain and it’s distinguished name. Then we create the filename for the image, this is simply the temp folder with “uap.jpg” as filename. With the distinguished name and the filename we can call the LoadPictureFromAD function and finally we run the useraccountpicture application with the username and the filename as parameters.

Save the script as .vbs – run it – have a look at the start menu – that’s all…

Now you can use this script as a logon script within group policies and all your users can find their photos in the start menu and on the lock screen.

7 Comments

  1. Thanks for the great script! It works like a charm! I’d like to add a slight modification so that if there isn’t a photo in AD it will just leave the default picture. I’m getting an error message that pops up for users that don’t have a picture in AD.

    Also would be nice if it could check for .net 4 and stop if it’s not installed. I also got that error message that .net 4 was needed.

    I’d like this to be invisible for all users, so that they don’t question weird error messages popping up.

    Thanks again!

    Ryan Breneman
    Systems Administrator
    Hempfield School District

  2. @Ryan Breneman
    Hi, thanks for your comment. There should be no .net error message from the script. It may appear if you compiled the useraccountpicture.exe with .net framework 4. You can simply change that in Visual Studio to version 2 or 3 if you like. Please tell me if I was correct and if it worked for you.

  3. @Norman Bauer
    Thanks Norman, you were exactly right. Once I changed that in visual studio and re-compiled that went away.

    Would you be able to shed any light on how to modify the script to allow for users that don’t have a thumbnailphoto?

    Thanks again!
    Ryan

  4. @Ryan Breneman
    Hi Ryan,

    I didn’t test the code below, but give it a try…

    Function LoadPictureFromAD(szADsPath, szSaveFileName)
        Const E_ADS_PROPERTY_NOT_FOUND = &h8000500D 
        Dim objUser, bytesRead, adoStreamWrite
        Const adTypeBinary = 1, adSaveCreateOverWrite = 2
    
        On Error Resume Next
     
        Set objUser = GetObject(szADsPath)
        bytesRead = objUser.Get("thumbnailPhoto")
    
        If Err.Number = E_ADS_PROPERTY_NOT_FOUND Then 
            LoadPictureFromAD = false
        Else   
            Set adoStreamWrite = CreateObject("ADODB.Stream")
            adoStreamWrite.Type = adTypeBinary
            adoStreamWrite.Open
            adoStreamWrite.Write(bytesRead)
            adoStreamWrite.SaveToFile szSaveFileName, adSaveCreateOverWrite
            adoStreamWrite.Close
            LoadPictureFromAD = true
        End If 
    
        On Error Goto 0
    End Function
     
    Set wshShell = CreateObject("WScript.Shell")
    Set fso = CreateObject("Scripting.FileSystemObject")
     
    workingdir = Replace(wscript.scriptfullname, Wscript.scriptname, "")
     
    Set wshNetwork = WScript.CreateObject("WScript.Network")
    username = wshNetwork.UserDomain  & "\" & wshNetwork.UserName
    Set objSysInfo = CreateObject("ADSystemInfo")
    strUserName = objSysInfo.UserName
    dn = "LDAP://" & strUserName
     
    path = wshShell.ExpandEnvironmentStrings("%temp%") & "\"
    filename = path & "uap.jpg"
     
    If LoadPictureFromAD(dn, filename) = true Then
        wshshell.run workingdir & "useraccountpicture.exe " & username & " " & filename, 0, true
    End If
    
  5. @Norman Bauer

    That did the trick! Thanks so much for your help.
    -Ryan

  6. useraccountpicture.exe is not display picture in Windows 8

  7. I know… I did not find a way to accomplish this in Windows 8 yet.

Leave a Reply

Your email address will not be published. Required fields are marked *

Captcha: * Time limit is exhausted. Please reload CAPTCHA.