将照片调整为与Active Directory兼容的格式

时间:2018-11-12 16:34:26

标签: .net powershell active-directory

我具有一个功能,可以调整从外部系统接收到的图像的大小,然后进入Active Directory以符合大小限制,但是它似乎不起作用。当我使用此代码调整图像大小时,它似乎不兼容,尝试设置图像会产生错误。

如果我打开此图像,看起来不错。如果我然后使用图像编辑器将其保存,则可以将其导入到AD中,因此该功能肯定不完全正确,我认为这与编码有关,但是我不知道该如何解决它。

我可以使用以下代码加载照片(对于AD而言太大的原始照片):

$original = [system.io.file]::ReadAllBytes('C:\original.jpg')

然后我调整其大小并尝试将其添加到AD中,这会失败。

$scaled = ResizeImage -ImageData $original -Percentage 80
Set-ADUser user -Replace @{ thumbnailPhoto=$scaled } 

这给我

的错误
  

Set-ADUser:为一个只能指定一个值的属性指定了多个值

  

Set-ADUser:无法联系服务器。这可能是因为该服务器不存在,当前已关闭或没有运行Active Directory Web服务。

取决于它的运行方式和运行位置。我已经确认这与权限或连接性无关,因为我可以写入在此过程中无法缩放的其他数据和图像。

如果我将$ Scaled图像写入磁盘,则可以使用图像编辑器重新保存它,从而可以完成此工作。功能在下面,任何帮助将不胜感激!

function ResizeImage {
[CmdletBinding()]
Param (
    [Parameter(Mandatory)]
    [byte[]]
    $ImageData,

    [Parameter(Mandatory)]
    [double]
    $Percentage,

    [Parameter()]
    [ValidateSet('HighQuality', 'HighSpeed', 'Antialias', 'Default', 'None')]
    [string]
    $SmoothingMode = "Default",

    [Parameter()]
    [ValidateSet('Bicubic', 'Bilinear', 'HighQualityBicubic', 'HighQualityBilinear', 'Default', 'High', 'Low', 'NearestNeighbor')]
    [string]
    $InterpolationMode = "Default",

    [Parameter()]
    [ValidateSet('HighQuality', 'HighSpeed', 'Half', 'Default', 'None')]
    [string]
    $PixelOffsetMode = "Default"
)
Begin {
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
}
Process {
    $ImageBase64 = [System.Convert]::ToBase64String($ImageData)
    $ImageMemory = [System.IO.MemoryStream][System.Convert]::FromBase64String($ImageBase64)
    $Bitmap = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($ImageMemory)
    $Product = $Percentage / 100
    [int]$NewHeight = $Bitmap.Height * $Product
    [int]$NewWidth = $Bitmap.Width * $Product

    $NewMemory = [System.IO.MemoryStream]::New()
    $NewBitmap = [System.Drawing.Bitmap]::New($NewWidth, $NewHeight)
    $NewImage = [System.Drawing.Graphics]::FromImage($NewBitmap)
    $NewImage.SmoothingMode = $SmoothingMode
    $NewImage.InterpolationMode = $InterpolationMode
    $NewImage.PixelOffsetMode = $PixelOffsetMode
    $NewImage.DrawImage($Bitmap, $(New-Object -TypeName System.Drawing.Rectangle -ArgumentList 0, 0, $NewWidth, $NewHeight))
    $NewBitmap.Save($NewMemory, [System.Drawing.Imaging.ImageFormat]::Jpeg)
    [byte[]]$NewMemory.ToArray()
}
}

1 个答案:

答案 0 :(得分:0)

对于广告thumbnailPhoto,最大尺寸为96x96像素,因此我通常使用这样的功能使原始图像适合那个小正方形。 与其使用要求您给出百分比的函数,不如简单地使用这些最大值。尺寸。

这是调整原始图像大小的帮助器功能:

function Shrink-Image {
    # helper function to resize an image so it fits inside the given "TargetSize"
    # It returns the path and filename of the resized image or the path to the original image if
    # that happened to fit inside the "TargetSize" square.
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true, Position=0)]
        [Alias("FileName")]
        [ValidateScript({Test-Path $_ -PathType Leaf})]
        [string]$ImagePath, 

        [Parameter(Mandatory=$true, Position=1)]
        [int]$TargetSize,

        [int]$Quality = 90
    )

    Add-Type -AssemblyName "System.Drawing"

    $img = [System.Drawing.Image]::FromFile($ImagePath)

    # if the original image fits inside the target size, we're done
    if ($img.Width -le $TargetSize -and $img.Height -le $TargetSize) {
        $img.Dispose()
        return $ImagePath
    }

    # set the encoder quality
    $ImageEncoder = [System.Drawing.Imaging.Encoder]::Quality
    $encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
    $encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($ImageEncoder, $Quality)

    # set the output codec to jpg
    $Codec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object {$_.MimeType -eq 'image/jpeg'}

    # calculate the image ratio
    $ratioX = [double]($TargetSize / $img.Width)
    $ratioY = [double]($TargetSize / $img.Height)
    if ($ratioX -le $ratioY) { $ratio = $ratioX } else { $ratio = $ratioY }

    $newWidth  = [int]($img.Width * $ratio)
    $newHeight = [int]($img.Height * $ratio)
    $newImage  = New-Object System.Drawing.Bitmap($newWidth, $newHeight)

    $graph = [System.Drawing.Graphics]::FromImage($newImage)
    $graph.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic

    $graph.Clear([System.Drawing.Color]::White)
    $graph.DrawImage($img, 0, 0, $newWidth, $newHeight)

    # save the new image as temp file
    $OutputPath = [System.IO.Path]::GetTempFileName()

    # For safety: a [System.Drawing.Bitmap] does not have a "overwrite if exists" option for the Save() method
    if (Test-Path $OutputPath) { Remove-Item $OutputPath -Force }
    $newImage.Save($OutputPath, $Codec, $($encoderParams))

    $graph.Dispose()
    $newImage.Dispose()
    $img.Dispose()

    return $OutputPath
}

如果需要,将其调整为给定的$TargetSize,并返回此调整大小后的图像的完整路径和文件名。 (注意:如果返回的路径恰好位于$TargetSize方块内,则返回的路径也可以与原始图像相同)

接下来,该功能实际上是在用户的AD thumbnailPhoto属性中设置图片:

function Set-ADUserPicture {
    [CmdletBinding(DefaultParameterSetName = 'ByName')]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ByName', Position = 0)]
        [String]$Identity,    # This can be: Distinguished Name, objectGUID, objectSid, sAMAccountName

        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ByObject', Position = 0)]
        [Object]$User,        # This is the user object from Get-ADUser

        [Parameter(Mandatory = $true, Position = 1)]
        [String]$ImageFile
    )
    if ($PSCmdlet.ParameterSetName -eq 'ByName') {
        $User = Get-ADUser -Identity $Identity
    }
    if ($User) {
        Write-Verbose ("Inserting userpicture in Active Directory for user {0}" -f $User.Name)
        try {
            # create a thumbnail using the original image, and size it down to 96x96 pixels
            $pictureFile = Shrink-Image -ImagePath $ImageFile -TargetSize 96
            [byte[]]$pictureData = [System.IO.File]::ReadAllBytes($pictureFile)
            $User | Set-ADUser -Replace @{thumbnailPhoto = $pictureData } -ErrorAction Stop
        }
        catch {
            Write-Error "Set-ADUserPicture: $($_.Exception.Message)"
        }
        finally {
            if ($pictureFile -ne $ImageFile) {
                # the original image was larger than 96x96 pixels, so we created a temp file. Remove that.
                Remove-Item $pictureFile -Force -ErrorAction SilentlyContinue
            }
        }
    }
}

您使用Set-ADUserPicture -Identity $SamAccountName -ImageFile $UserImagePath之类的身份进行调用 或使用您先前使用Get-ADUser cmdlet之类的$userObject | Set-ADUserPicture -ImageFile $UserImagePath

获得的用户对象

如果要对Office365个人资料图片执行类似操作,则最大尺寸为648x648像素。为此,您首先需要使用类似以下的命令登录:

$Cred    = Get-Credential -UserName "admin@yourdomain.com" -Message "Please enter admin credentials for Office365"
$Url     = "https://outlook.office365.com/powershell-liveid/?proxyMethod=RPS"
$Session = New-PSSession -ConfigurationName "Microsoft.Exchange" -ConnectionUri $Url -Credential $Cred -Authentication Basic -AllowRedirection

Import-PSSession $Session -DisableNameChecking -AllowClobber -WarningAction SilentlyContinue -ErrorAction SilentlyContinue | Out-Null

之后,下一个功能将设置该图像,类似于AD thumbnailPhoto的功能:

function Set-O365UserPicture {
    [CmdletBinding(DefaultParameterSetName = 'ByName')]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ByName', Position = 0)]
        [String]$Identity,    # This can be: Distinguished Name, objectGUID, objectSid, sAMAccountName

        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'ByObject', Position = 0)]
        [Object]$User,        # This is the user object from Get-ADUser

        [Parameter(Mandatory = $true, Position = 1)]
        [String]$ImageFile
    )
    if ($PSCmdlet.ParameterSetName -eq 'ByName') {
        $User = Get-ADUser -Identity $Identity
    }
    if ($User) {
        Write-Verbose ("Inserting userpicture in Office365 for user {0}" -f $User.Name)
        try {
            # shrink the original image, and size it down to 648x648 pixels
            $pictureFile = Shrink-Image -ImagePath $ImageFile -TargetSize 648
            [byte[]]$pictureData = [System.IO.File]::ReadAllBytes($pictureFile)
            $User | Set-UserPhoto -PictureData $pictureData -Confirm:$false -ErrorAction Stop
        }
        catch {
            Write-Error "Set-O365UserPicture: $($_.Exception.Message)"
        }
        finally {
            if ($pictureFile -ne $ImageFile) {
                # the original image was larger than 648x648, so we created a temp file. Remove that.
                Remove-Item $pictureFile -Force -ErrorAction SilentlyContinue
            }
        }
    }
}

您使用Set-O365UserPicture -Identity $SamAccountName -ImageFile $UserImagePath之类的身份进行调用 或使用您先前使用Get-ADUser cmdlet之类的$userObject | Set-O365UserPicture -ImageFile $UserImagePath

获得的用户对象

对于两个功能Set-ADUserPictureSet-O365UserPicture,建议同时添加-Verbose开关。