Results 1 to 1 of 1

Thread: Powershell - Active Directory Image Thumbnail importer

  1. #1
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default Powershell - Active Directory Image Thumbnail importer

    Info:
    For those of you not familiar with AD (Active Directory), it's basically an address book that stores all your users and information about that user and what permissions/groups they are part of.
    This script needs to be run by a domain admin and it goes through all domains you list in the array and imports a user image associated to the user in AD.

    How does this work exactly?
    The image needs to be named like so:
    LastName,FirstName.jpg ex Name: John Doe --> Doe,John.jpg
    The script recursively goes through each picture and makes sure that the formatting is correct (no additional spaces or anything like that)
    Then it converts the image into a proportional thumbnail that's 96x96 pixels, and imports it into the AD thumbnail

    Why would I use this?
    Let's assume you work in a company with 500+ employees. It can be difficult to put a face to every single person's name. With this script, after the image is imported into AD, when you use Exchange/Outlook, or any utility that integrates with AD, you will be able to see a small picture (like an avatar) of the user that you are emailing or looking up.

    How does this tool differ from other utilities?
    This is the first script I have ever written in powershell. This original concept isn't mine, however I heavily modified it to fit my needs, and I feel like it could be very useful for others. To answer the question though, I like this for a few reasons.
    1. It's free! How can you beat free?
    2. It supports multiple domains <-- To my surprise I haven't come across a utility or script that runs across multiple domains. The other tools I saw would have to be run separately on each domain, whereas this runs recursively on all domains.
    3. It recursively supports multiple instances of the same user. If some special user is listed on multiple domains, this script is able to detect it and associate the image across all domains. Believe it or not this is very useful
    4. It's simple to use, and because powershell is super "Windows friendly" it's convenient, portable, and easy on resources. I've ran other tools that would make my memory and CPU skyrocket. Some take a VERY long time to run an import photos and I've had other tools crash my OS 75% into the progress which sucks. Even after restarting my machine it kept crashing at around the same spot, and when I checked the resources my memory usage was at over 5Gb. This was absurd!


    Here are the files:

    GALBatchConvert.ps1

    param($InputFolder,$OutputFolder,$Quality);
    # GALBatchConvert.ps1
    # Use to convert large numbers of contact pictures to optimised 96x96 GAL photos
    # Script modified by James
    # Steve Goodman


    if (!$InputFolder -or !$InputFolder)
    {
    throw "InputFolder and OutputFolder parameters are mandatory";
    }
    if (!(Test-Path $InputFolder))
    {
    throw "InputFolder not found";
    }
    if (!(Test-Path $OutputFolder))
    {
    throw "OutputFolder not found";
    }


    #This just gets the path of the output folder; which is where we will be placing these converted images to
    $FullOutputFolderPath = (Get-Item $OutputFolder).FullName
    $Items = Get-ChildItem $InputFolder


    if ($Items.Count -eq 0)
    {
    throw "No items in folder"
    }


    [array]$ValidExt=".jpg",".jpeg",".bmp",".tif",".tiff",".gif",".png"


    foreach ($Item in $Items)
    {
    $FileName = ($Item.name).split('.')[0] #We are removing the extension from the file name
    $LastName = $FileName.split(',')[0] #This is the last name before the comma ','
    $FirstName = $FileName.split(',')[1] #This is the first name after the comma ','
    <#
    The lines below are commented out because we don't use them, but you can use them if you choose to.
    $FirstNameChar = first initial of first name
    $LastNameChars = first 6 characters of last name
    For example if the user we are working with was James Kulikowski
    The output would be "jkuliko" after putting the two together like so $FirstNameChar + $LastNameChars
    #>
    #$FirstNameChar = $FirstName.substring(0,1) # this just get's the first character of the first name
    #$LastNameChars = $LastName.substring(0,6) # 6 characters of last name
    #$PictureName = $LastName + ',' + $FirstName + '.JPG'
    #$PictureName = $FirstNameChar + $LastNameChars

    <#
    Basically here we are grabbing the image and we will be renaming it from "LastName, FirstName.jpg" to "FirstName LastName.jpg"
    This will allow us to search the file name and compare it to the user later in the code.
    #>
    $PictureName = $FirstName + " " + $LastName

    #This if statement isn't necessarily required, but it just checks to make sure the extension is valid. It checks the array of extensions above
    if ($ValidExt -contains $Item.Extension)
    {
    #This is just an output that lets us know which image is currently being processed/converted
    Write-Output "Converting $($Item.FullName)"

    #This is the conversion piece
    #Quality = 100% so it won't look distorted
    #Depth = 32 bit (MAX)
    #thumbnail size is 96x96
    #And the final output will go into the Output folder with "FirstName LastName.jpg" of the user
    .\convert.exe -quality 100 -depth 32 -strip -thumbnail 96x96^ $Item.FullName "$($FullOutputFolderPath)\$($PictureName).jpg"
    }
    }


    SetUserThumbnailPhoto.ps1 <-- Main script you run

    #This is the path to the original photos
    $InputFolder = "\\This\Is\The\Path\to\Original\Picture\" #<-- Don't forget trailing "\"
    #This is the path we copy the pictures in to from the path above, after we resize them into thumbnails
    $OutputFolder = "C:\ADPhotos\Output" #This is the path that will post the thumbnail pictures after they are converted
    #As we process the images they will be copied from the path above to this path, and then we delete the image from this path when we're done importing it
    $ConvertedFolder = "C:\ADPhotos\Converted" #<-- This is a temp folder that images go into during the import process and after it's imported it gets cleared out
    #This is the base path of our script
    $ScriptLocation = "C:\ADPhotos\" #<-- This is the root location of this script. Notice the trailing "\" again.


    #Add the import and snapin in order to perform AD functions
    Add-PSSnapin Quest.ActiveRoles.ADManagement -ea SilentlyContinue
    Import-Module ActiveDirectory


    #Set the base path where our scripts run from
    Set-Location $ScriptLocation


    #This is used as a time stamp for our log files
    $Date = Get-Date -Format o | foreach {$_ -replace ":", "."}


    #First we will call a script to rename the images if they need to be renamed for consistency purposes
    .\Rename.ps1


    #This calls a seperate powershell script that will convert the image into a thumbnail.
    .\GALBatchConvert.ps1 -InputFolder $InputFolder -OutputFolder $OutputFolder


    #This line retrieves all files from the path in the "Input Folder" - referenced at the very top
    $Pictures = Get-ChildItem $OutputFolder


    #List the domains we want to cycle through
    [array]$TotalDomains="domain1.local","domain2.org","domain3.com"


    foreach ($Item in $Pictures)
    {
    #Extract the name of the photo without the extension
    $FileName = ($Item.name).split('.')[0] #We are removing the extension from the file name


    #The next 3 lines of code are a little trick to implement wild cards in the name so that we make sure we don't miss someone
    $FirstName = $FileName.split(' ')[0] #This is the first name after the comma ','
    $LastName = $FileName.split(' ')[1] #This is the last name before the comma ','
    $ModifiedName = "*"+ $FirstName + "*" + $LastName + "*"


    <#
    Since we are searching AD from the file name, we will NEVER get a false positive in the sense of a image accidentally being uploaded to another user
    The ONLY acception to the rule is if we have multiple users with the same display name
    Get user by displayname from AD
    #>

    #Hackish code to check for multiple spaces in a name
    $WithSpaces = ($FileName | Measure-Object -character).Characters #First we need to count all characters with spaces
    [int]$intNumA = [convert]::ToInt32($WithSpaces, 10) #Convert the output to integer value from string
    $WithoutSpaces = ($FileName | Measure-Object -ignoreWhiteSpace -character).Characters #Now we count all characters without spaces
    [int]$intNumB = [convert]::ToInt32($WithoutSpaces, 10) #Convert the output to integer value from string
    $NumberOfSpaces = ($intNumA - $intNumB) #Now we do some subtraction to get the number of spaces in our file name.

    If ($NumberOfSpaces -le 1)
    {
    #If there is only 1 space, we don't need to do anything
    }
    Else
    {
    <#
    NOTE: Here we look for user names with multiple spaces because some user names are "special". For example "John Doe Bob"
    We add substitute wild cards, so in this example it would search for "*John*Doe*Bob*".
    #>
    #If there are 2 or more spaces, we will replace each one with a "*" and assign it to $ModifiedName
    $FileName -replace " ","*"
    $ModifiedName = "*"+ $FileName + "*"
    }

    #This loop checks against all 3 domains. The array of domains is defined above.
    for($i=0; $i -lt $TotalDomains.Count; $i++)
    {
    $user = $(try {Get-ADUser -Filter{displayName -like $ModifiedName -and SamAccountName -notlike "admin-*" -and Enabled -eq $True} -server $($TotalDomains[$i]) -Properties SamAccountName, GivenName, Surname, telephoneNumber, mail} catch {$null})


    if ($user -ne $null)
    {
    # User EXISTS in this domain
    Write-Output "Importing $($Item.FullName) for $($FileName)"

    #Gain access to the picture
    $Owner = $Item | Get-Acl | select Owner -ExpandProperty Owner
    $PictureName = $Item.Name
    $PictureLength = $PictureName.Length
    $ConvertedPicture = $OutputFolder + "\" + ($PictureName.Substring(0,$PictureLength-3)) + "jpg"


    #Copy the thumbnail into the conversion folder
    Copy-Item -Path $ConvertedPicture -Destination $ConvertedFolder

    #Import the photo to the user
    $PictureContent = [byte[]](Get-Content $ConvertedFolder\* -Encoding byte)
    Get-ADuser $user | Set-ADUser -Replace @{thumbnailPhoto=$PictureContent} | out-file ".\logs\log$date.txt" -Append


    #Pause for a second
    sleep 1


    #Remove the picture we already imported so it doesn't somehow by mistake get imported again
    get-childitem $ConvertedFolder | Remove-Item
    }
    else
    {
    # User DOESN'T exist in this domain
    #Don't do anything, just continue
    }
    }
    }


    Rename.ps1

    <#
    This script is pretty simple and what it does is rename the images.
    There was an issue I ran in to that appended 2 extensions to each image.
    For Ex: LastName, FirstName.jpg.JPG
    I also noticed that some file names have spaces in them and others don't have a space. It is important to have consistency with all images
    This script will check all files that have a ".jpg.JPG" extension and will rename it to ".JPG"
    It will also remove spaces
    #>
    $InputFolder = "\\This\Is\The\Path\to\Original\Picture\" #<-- Don't forget trailing "\"


    #This converts the pictures from an invalid extension ".jpg.JPG" to ".JPG"
    #Initially when the image was being saved the extension was being appended twice, and we don't want that


    <#
    NOTE: With the piece that removes the spaces, the reason we are checking for a space with a comma is because
    that is the "cut off" for first and last name. Some user names are "special". For example "Bob, John Doe"
    If we removed all spaces, the name would show up as JohnDoe. This is no longer valid when we do a search in AD.
    #>


    Get-ChildItem $InputFolder |ForEach-Object{
    Write-Output "Converting $($_.FullName)"
    $NewName = $_.Name -replace ".jpg.JPG",".JPG" #Rename ".jpg.JPG" to just ".JPG"
    $NewName = $_.Name -replace ", ","," #Remove unnecessary space right of comma
    $NewName = $_.Name -replace " ,","," #Remove unnecessary space left of comma
    $Destination = Join-Path -Path $_.Directory.FullName -ChildPath $NewName
    Move-Item -Path $_.FullName -Destination $Destination -Force
    }
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •