# encoding: ascii
# api: powershell
# title: Import-GalPhoto
# description: a function to batch import Exchange 2010 GAL photos… find the related post on ntsystems.it: http://www.ntsystems.it/post.aspx?id=e28854e0-e628-4fc7-850b-83d0458d9ab7
# version: 0.1
# type: script
# author: thomas torggler
# license: CC0
# function: Import-GalPhoto
# x-poshcode-id: 3570
# x-archived: 2012-12-21T01:50:49
# x-published: 2012-08-12T07:01:00
#
#
<#
.Synopsis
   Import Exchange 2010 Gal photo for one or more users. 
.DESCRIPTION
   This function invokes the Import-RecipientDataProperty cmdldet to import a picture into the thumbnailPhoto attribute of an Exchange mailbox.
   It assumes you have a directory containing all images to import, with the file names corresponding to the usernames of the mailboxes.
   
   PS X:\> dir *.jpg


        Directory: c:\temp\pics


    Mode                LastWriteTime     Length Name
    ----                -------------     ------ ----
    -a---        07.08.2012     19:29       5984 user1.name.jpg
    -a---        16.05.2012     11:58       5984 user2.jpg
    -a---        23.07.2012     15:55       5984 user3.name.jpg
    ...

.EXAMPLE
   PS C:\> Import-GalPhoto -FilePath 'c:\temp\pics'
   This example gets all .jpg pictures from c:\temp\pics and tries to find corresponding Exchange Users. If a user is found, the picture is imported using Import-RecipientDataProperty.
.EXAMPLE
   PS C:\> dir 'c:\temp\pics' | Select-Object -First 2 | Import-GalPhoto
   This example shows how you can use Get-ChildItem (dir) and do some custom filtering (Where-Object, Select-Object) to get pictures. 
   Then it makes use of pipeline input to import pictures.
#>
function Import-GalPhoto
{
    [CmdletBinding(SupportsShouldProcess=$true, 
                  ConfirmImpact='High')]
    Param
    (
        # Set the FilePath where pictures are located
        [Parameter(Mandatory=$true, 
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [Alias('FullName')]
        [IO.FileInfo]
        $FilePath,

        # LogFile set the destination for LogFile, defaults to ".\Import-GalPhoto.txt" 
        [Parameter(Mandatory=$false,
                   ParameterSetName='Parameter Set 1')]
        $LogFile=".\Import-GalPhoto.txt"
    )

    Begin
    {
        Write-Verbose 'Execute Begin Block'
        # delete LogFile
        Remove-Item $LogFile -ErrorAction SilentlyContinue
        
        # load assembly, used to get Image Properties
        [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

        # logging
        "$(Get-Date) Function begin" | Add-Content -Path $LogFile -WhatIf:$false
    }
    Process
    {
        Write-Verbose 'Execute Process Block'

        # create an array that contains all files
        [array]$arrPics = Get-ChildItem -Path $FilePath -File -Filter '*.jpg'
        "$(Get-Date) arrPics is $($arrPics)" | Add-Content -Path $LogFile -WhatIf:$false

        $arrPics | ForEach-Object {
            # objPicture contains full path to the picture
            [IO.FileInfo]$objPicture = $_.FullName
            
            # assume file BaseName equals UserName
            [string]$strUserName = $_.BaseName
            
            # logging
            Write-Verbose "`$objPicture is $objPicture"
            Write-Verbose "`$strUserName is $strUserName"
            "$(Get-Date) objPicture is $($objPicture)" | Add-Content -Path $LogFile -WhatIf:$false
            "$(Get-Date) strUserName is $($strUserName)" | Add-Content -Path $LogFile -WhatIf:$false
    
            # some verification before manipulating stuff
            try {
                Write-Verbose "Try to find User $strUserName"
                Start-Sleep -Seconds 1
                $exchangeUser = Get-User -Identity $strUserName -ErrorAction Stop
                $Continue = $true

                # get Image Properties
                $objImage = [System.Drawing.Image]::FromFile($objPicture)

                # get content from image file, used with Import-RecipientDataProperty
                $objFileData = ([Byte[]]$(Get-Content -Path $objPicture -Encoding Byte -ReadCount 0 -ErrorAction Stop))
                    
                # logging
                Write-Verbose "`$exchangeUser is $($exchangeUser.SamAccountName)"
                Write-Verbose "`$objImage PhysicalDimensionis is $($objImage.PhysicalDimension)"
                Write-Verbose "`$objPicture filesize(KB) is $($objPicture.Length / 1kb)"
                "$(Get-Date) exchangeUser is $($exchangeUser.SamAccountName)" | Add-Content -Path $LogFile -WhatIf:$false
                "$(Get-Date) Image PhysicalDimension is $($objImage.PhysicalDimension)" | Add-Content -Path $LogFile -WhatIf:$false
                "$(Get-Date) Image filesize(KB) is $($objPicture.Length / 1kb)" | Add-Content -Path $LogFile -WhatIf:$false

            } catch {
                $Continue = $false

                # logging
                Write-Warning "Could not find User $strUserName"
                "$(Get-Date) Could not find $($strUserName)" | Add-Content -Path $LogFile -WhatIf:$false
            }
            
            # use objImage to check if image size is ok, max 96x96 pixels, max 10K
            if ($Continue -and (($objImage.Height -le 96) -and ($objImage.Width -le 96) -and ($objPicture.Length -le 10kb))){
                $Continue = $true

                # get rid of objImage
                $objImage.Dispose()                

                # logging
                Write-Verbose "Picture $($objPicture) is ok"
            } else {
                $Continue = $false
                
                # logging
                Write-Verbose "Picture $($objPicture) is not ok"
                "$(Get-Date) Skipped $($objPicture) size not ok" | Add-Content -Path $LogFile -WhatIf:$false
            }
                    
            # if verification is ok, go ahead and import images
            if ($Continue -and ($pscmdlet.ShouldProcess("$($exchangeUser.SamAccountName)", "Importing Recipient Data Property from file $objPicture"))) {
                
                # invoke Import-RecipientDataProperty to import data into active directory
                Import-RecipientDataProperty -Identity $exchangeUser.Identity -Picture -FileData $objFileData    
            }
        }
    }
    End
    {
        Write-Verbose 'Execute End Block'
        
        # logging
        "$(Get-Date) Function end" | Add-Content -Path $LogFile -WhatIf:$false
    }
}
