daily import photo's into active directory

This topic contains 16 replies, has 3 voices, and was last updated by Profile photo of Глеб Боушев Глеб Боушев 8 months ago.

  • Author
    Posts
  • #37232
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

    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

  • #37233

    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.

  • #37239
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

    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

  • #37260
    Profile photo of Richard Diphoorn
    Richard Diphoorn
    Participant

    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!

  • #37280
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

    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

  • #37284
    Profile photo of Richard Diphoorn
    Richard Diphoorn
    Participant

    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.

  • #37289
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

    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

    }

  • #37291
    Profile photo of Richard Diphoorn
    Richard Diphoorn
    Participant

    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. 🙂

  • #37293
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

    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

  • #37295
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

    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

    }

  • #37297
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

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

  • #37298
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

    Nope, I can not figure it out.

  • #37300
    Profile photo of Richard Diphoorn
    Richard Diphoorn
    Participant

    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))}
            }
    }
    
  • #37307

    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.

  • #37308
    Profile photo of Richard Diphoorn
    Richard Diphoorn
    Participant

    Глеб Боушев, 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.

  • #37313
    Profile photo of Twan Veugelers
    Twan Veugelers
    Participant

    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

  • #37314

    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.

You must be logged in to reply to this topic.