Author Posts

April 5, 2016 at 12:36 am

Hi.

I have a folder that contains files.
They are named xxxxx.jpg
xxxxx correspondents with the employeeid field in AD.
Now I want to daily schedule a PS script that scans all the files, and if the employeeid correspondents with filename, it should upload the photo into AD for that user.

What information is needed to provide me with an answer?

grtz,
Twan

April 5, 2016 at 12:57 am

Hello, this should be fairly straight forward thing.
You tried googling that? 😉
There are tons of stuff on this problem out there
https://coffeefueled.org/powershell/importing-photos-into-ad-with-powershell/

but your general approach would be get-childitem to get get all the pictures into a variable, after that you read them one by one as bytes and pipe to set-aduser.

April 5, 2016 at 3:26 am

Hi.

Yes I have tried to search for it, and even the example you link to does probably import photos into AD. But my PS skills are not very high, so I would not know how to modify the script to satisfy my needs.

grtz,
Twan

April 5, 2016 at 1:35 pm

Hello Twan, welcome to the forum. I'll try to help you a bit with this.

First of all I wanted to say to Глеб Боушев, that even though the response "did you googled that", can be funny, it is not really a helpful answer to a valid question. The purpose of community is to help out each other. That said, here's my proposed answer.

The credits of this solution goes to Joseph Moody ( https://deployhappiness.com/importing-photos-active-directory-outlook-powershell/ ). I just modified the script Set-UserThumbnailPhoto.ps1 so that it will work with the Active Directory attribute employeeID.

One important thing to notice; Joseph makes use of the Quest AD Cmdlets, and I changed the script to make use of the native Active Directory Cmdlets. So make sure you have the latest RSAT tools installed on the machine you run this script from.

Please notice, I didn't had a AD to my disposal, so forgive me if the solution doesn't work. The script Set-UserThumbnailPhoto.ps1 is as following:

#requires -Version 1
#requires -Modules ActiveDirectory

$inputFolder 		= '\\Server\Share\EmailPhoto\'
$outputFolder 		= 'C:\Users\Public\Scripts\ADPhotos\Output\'
$convertedFolder 	= 'C:\Users\Public\Scripts\ADPhotos\Converted\'
$scriptLocation 	= 'C:\Users\Public\Scripts\ADPhotos\'
$pictures 			= Get-ChildItem $inputFolder

Set-Location $scriptLocation
.\GALBatchConvert.ps1 -InputFolder $inputFolder -OutputFolder $outputFolder

foreach ($picture in $pictures){
    $user 				= Get-ADUser -Filter "EmployeeID -eq $($picture.BaseName)" -Properties SAMAccountName
    $pictureName 		= $picture.Name
    $pictureLength 		= $pictureName.Length
    $convertedPicture 	= $outputFolder + ($pictureName.Substring(0,$pictureLength-3)) + 'jpg'

    Copy-Item -Path $convertedPicture -Destination $convertedFolder

    $pictureContent = [byte[]](Get-Content -Path $convertedFolder\* -Encoding byte)
    $user | Set-ADUser -Replace @{
        thumbnailPhoto = $pictureContent
    }

    Start-Sleep -Seconds 5 

    Get-ChildItem $convertedFolder | Remove-Item -Confirm:$false
}

Remove-Item -Path $inputFolder\* -Recurse
Remove-Item -Path $outputFolder\* -Recurse

What you will need to do is this:

  1. Download the scriptfiles here: https://rdiphoorn.stackstorage.com/index.php/s/Ck7FV2deLayFgrm
  2. Unblock the zip file (rightclick on the file, unblock)
  3. Unzip the ADPhotos folder to C:\Users\Public\Scripts\
  4. Launch ISE and open the Set-UserThumbnailPhoto.ps1 script
  5. Modify the location of the input folder where you have the original pictures (should be *.jpg)
  6. Make sure the folders at $outputFolder, $convertedFolder,$scriptLocation exists
  7. Save the script
  8. Place just one picture in the actual folder which you specified in $inputFolder, to test it on one AD user object
  9. Run the script
  10. The logic it will take to set the picture is described by Joseph Moody in the link I gave.

    I hope this will help you!

April 5, 2016 at 11:47 pm

Hi Richard.

This is a great help, but it would be even nicer if I can select on OU in the AD domain that serves as a filter. Unfortunatly we have several entities with their own employee number system that share the same AD dB.

But users in a single OU do not have the same employeeID.

Is it possible to make this distinguish in the script?

grtz,
Twan

April 6, 2016 at 12:32 am

First in the start of the script declare an OU name:

$ou = 'OU=Users,DC=domain,DC=com'

Then if you change the code behind $users from
Get-ADUser -Filter "EmployeeID -eq $($picture.BaseName)" -Properties SAMAccountName

To:

Get-ADUser -Filter "EmployeeID -eq $($picture.BaseName)" -Properties SAMAccountName -SearchBase $ou

you should be able to narrow down the search within the specified OU.

April 6, 2016 at 12:58 am

Hi Richard.

As my originals are already 96×96 in size (yes, the are taken and saved in 96×96 originaly).
I think I will remove the whole galbatch+outputfolder+convertedfolder.
Plus I don't want any pictures removed from my input location. (I guess)
Or will this give me a problem with large number of files?

Could you please check the code below?
#requires -Version 1
#requires -Modules ActiveDirectory

$ou = 'OU=Venray,DC=eu,DC=mycompany,DC=local'
$inputFolder = '\\eu\dfs1\PhotoDir\NL\'
$pictures = Get-ChildItem $inputFolder

foreach ($picture in $pictures){
$user = Get-ADUser -Filter "EmployeeID -eq $($picture.BaseName)" -Properties SAMAccountName -SearchBase $ou

$pictureContent = [byte[]](Get-Content -Path $inputFolder\* -Encoding byte)
$user | Set-ADUser -Replace @{
thumbnailPhoto = $pictureContent
}

Start-Sleep -Seconds 5

}

April 6, 2016 at 1:43 am

I don't see the need for converting if the pictures are already in the right format. So your code will work. Just try to do it on a few user object, so that you don't screw up all the users when something is wrong. 🙂

April 6, 2016 at 2:47 am

Hi Richard.

Thank you very much for your assistance. This worked brilliantly.
Just a quick question. Is there any reason for "sleeping" 5 seconds?
I guess with importing 100 pictures, this would accumulate to 500 seconds of wait time.

grtz,
Twan

April 6, 2016 at 2:57 am

Hi Richard.

I was to quick to celebrate.
For some reason what he does is the following.
I have two pictures in the folder now:
40086.jpg
40266.jpg

Now what happens is, that for both user 40086 and 40266 picture 40086.jpg is imported.
Other users are not touched (phew).

Once again the code I use at this moment:
#requires -Version 1
#requires -Modules ActiveDirectory

$ou = 'OU=Venray,DC=eu,DC=mycompany,DC=local'
$inputFolder = '\\eu\dfs1\PhotoDir\NL\'
$pictures = Get-ChildItem $inputFolder

foreach ($picture in $pictures){
$user = Get-ADUser -Filter "EmployeeID -eq $($picture.BaseName)" -Properties SAMAccountName -SearchBase $ou

$pictureContent = [byte[]](Get-Content -Path $inputFolder\* -Encoding byte)
$user | Set-ADUser -Replace @{
thumbnailPhoto = $pictureContent
}

Start-Sleep -Seconds 5

}

April 6, 2016 at 2:59 am

Probably I was to rigorous in my removing of code.
I guess I lost the declaration of basename somewhere.

April 6, 2016 at 3:05 am

Nope, I can not figure it out.

April 6, 2016 at 4:06 am

My bad. The code was taking in all the pictures and put it on 1 user object indeed, as you already figured out. Here's the revised code:

#requires -Version 1
#requires -Modules ActiveDirectory

$ou					= 'OU=Venray,DC=eu,DC=mycompany,DC=local'
$inputFolder 		= '\\eu\dfs1\PhotoDir\NL\'
$pictures 			= Get-ChildItem $inputFolder

foreach ($picture in $pictures){
    
    Try {
        $user = Get-ADUser -Filter "EmployeeID -eq $($picture.BaseName)" -Properties SAMAccountName -SearchBase $ou -ErrorAction Stop
        }
    
    Catch {
        Write-Warning "Warning: $_"
    }

    If ($user) {
        $user | Set-ADUser -Replace @{thumbnailPhoto = ([byte[]](Get-Content -Path $inputFolder\$($picture.Name) -Encoding byte))}
        }
}

April 6, 2016 at 4:45 am

Well, actually if you tried clicking the link that I provided you could've noticed that script from that blog post works fine. I'm not sure if its okay to ask other people to do all the work for you, your mileage may vary, but I've given the person asking a solid starting point, that does what he needs, but that script works with file names a little, as the person writing that had files named as name_surname.jpg. I don't think that any sane person should expect me to do that persons work for them. I'm in no way saying that a person cannot ask for help, but doing at least something seems reasonable to me.

April 6, 2016 at 4:56 am

Глеб Боушев, in my opinion it's not really polite to refer to "google it". I'm pretty sure that the requester already did that. And from the question of the requester you've seen that he needs help with PowerShell. You directed him to a script which contains mistakes and refers to custom objects. So yes, I actually clicked the link and analyzed that script.

Instead, I have tried to provide a helpful question. I've chosen in this post to provide more or less a complete solution, because it's something that I sometimes encounter. I'm also learning from this. And I'm pretty sure Twan is also learning from this.

April 6, 2016 at 5:13 am

Hi Richard.

You are my personal god for today, many thanks.

I could not have figured it out without your help.
Many Many thanks.

grtz,
Twan

April 6, 2016 at 5:17 am

Well, I'm not really good at guessing, but Twan didn't really say what he fails to do in his post, his question was general so was my answer. I pointed him to a similar and working example, I've given him top level ideas how to achieve what he needs. I have no idea what I've done wrong.