Script to Add Custom Icons to a Horizon Application

Script to add icon to horizon application

Quick way to get a list of icons:

Get-HVApplication | Select-Object name,displayname |Export-Csv -path C:\HVIcons\newlist.csv

I wrote the following script to take a csv file of application name and description, and then connect to a Horizon Connection Server and cycle through the csv looking for an icon file in the format desc.png or desc-0.png and apply the icon to the application.

It is made up of three modules, one of which is a lightly modified version of a VMware staffer’s module, which included a load of “breaks” which I had to remove to ensure it would complete the full array.



############################################################
### Add Icons to Horizon Application from a CSV File
### .NOTES
###    Author                      : Chris Mitchell
###    Author email                : mitchellc@vmware.com
###    Version                     : 1.0
###
###    ===Tested Against Environment====
###    Horizon View Server Version : 7.7
###    PowerCLI Version            : PowerCLI 11.3
###    PowerShell Version          : 5.1
###
###    Add-HVAppIcon -h VCS01.local.net -csv apps.csv -u admin -p Password01
###
############################################################

param (
    [string]$h = $(Read-Host "Horizon Connection Server Name:"),
    [string]$c = $(Read-Host "csv filename:"),
    [string]$u = $(Read-Host "username:"),
    [string]$p = $(Read-Host "password:")
    )


function Get-ViewAPIService {
  param(
    [Parameter(Mandatory = $false)]
    $HvServer
  )
  if ($null -ne $hvServer) {
    if ($hvServer.GetType().name -ne 'ViewServerImpl') {
      $type = $hvServer.GetType().name
      Write-Error "Expected hvServer type is ViewServerImpl, but received: [$type]"
      return $null
    }
    elseif ($hvServer.IsConnected) {
      return $hvServer.ExtensionData
    }
  } elseif ($global:DefaultHVServers.Length -gt 0) {
     $hvServer = $global:DefaultHVServers[0]
     return $hvServer.ExtensionData
  }
  return $null
}



function HVApplicationIcon {
<#
.SYNOPSIS
   Used to create/update an icon association for a given application.

.DESCRIPTION
   This function is used to create an application icon and associate it with the given application. If the specified icon already exists in the LDAP, it will just updates the icon association to the application. Any of the existing customized icon association to the given application will be overwritten.

.PARAMETER ApplicationName
   Name of the application to which the association to be made.

.PARAMETER IconPath
   Path of the icon.

.PARAMETER HvServer
   View API service object of Connect-HVServer cmdlet.

.EXAMPLE
   Creating the icon I1 and associating with application A1. Same command is used for update icon also.
   Set-HVApplicationIcon -ApplicationName A1 -IconPath C:\I1.ico -HvServer $hvServer

.OUTPUTS
   None

.NOTES
    Author                      : Paramesh Oddepally.
    Author email                : poddepally@vmware.com
    Version                     : 1.1

    ===Tested Against Environment====
    Horizon View Server Version : 7.1
    PowerCLI Version            : PowerCLI 6.5.1
    PowerShell Version          : 5.0
#>

  [CmdletBinding(
    SupportsShouldProcess = $true,
    ConfirmImpact = 'High'
  )]

  param(
   [Parameter(Mandatory = $true)]
   [string] $ApplicationName,

   [Parameter(Mandatory = $true)]
   $IconPath,

   [Parameter(Mandatory = $false)]
   $HvServer = $null
  )

  begin {
    $services = Get-ViewAPIService -HvServer $HvServer
    if ($null -eq $services) {
      Write-Error "Could not retrieve ViewApi services from connection object."
      
    }
    Add-Type -AssemblyName System.Drawing
  }

  process {
	if (!(Test-Path $IconPath)) {
      Write-Error "File:[$IconPath] does not exist."
      
    }

    if ([IO.Path]::GetExtension($IconPath) -ne '.png') {
      Write-Error "Unsupported file format:[$IconPath]. Only PNG image files are supported."
      
    }

    try {
      $appInfo = Get-HVQueryResult -EntityType ApplicationInfo -Filter (Get-HVQueryFilter data.name -Eq $ApplicationName) -HvServer $HvServer
    } catch {
      # EntityNotFound, InsufficientPermission, InvalidArgument, InvalidType, UnexpectedFault
      Write-Error "Error in querying the ApplicationInfo for Application:[$ApplicationName] $_"
      
    }

    if ($null -eq $appInfo) {
      Write-Error "No application found with specified name:[$ApplicationName]."
      
    }

    $spec = New-Object VMware.Hv.ApplicationIconSpec
    $base = New-Object VMware.Hv.ApplicationIconBase

    try {
      $fileHash = Get-FileHash -Path $IconPath -Algorithm MD5
      $base.IconHash = $fileHash.Hash
      $base.Data = (Get-Content $iconPath -Encoding byte)
      $bitMap = [System.Drawing.Bitmap]::FromFile($iconPath)
      $base.Width = $bitMap.Width
      $base.Height = $bitMap.Height
      $base.IconSource = "broker"
      $base.Applications = @($appInfo.Id)
      $spec.ExecutionData = $base
    } catch {
      Write-Error "Error in reading the icon parameters: $_"
      
    }

    if ($base.Height -gt 256 -or $base.Width -gt 256) {
      Write-Error "Invalid image resolution. Maximum resolution for an icon should be 256*256."
      
    }

    $ApplicationIconHelper = New-Object VMware.Hv.ApplicationIconService
    try {
      $ApplicationIconId = $ApplicationIconHelper.ApplicationIcon_CreateAndAssociate($services, $spec)
    } catch {
        if ($_.Exception.InnerException.MethodFault.GetType().name.Equals('EntityAlreadyExists')) {
           # This icon is already part of LDAP and associated with some other application(s).
           # In this case, call updateAssociations
           $applicationIconId = $_.Exception.InnerException.MethodFault.Id
           Write-Host "Some application(s) already have an association for the specified icon."
           $ApplicationIconHelper.ApplicationIcon_UpdateAssociations($services, $applicationIconId, @($appInfo.Id))
           Write-Host "Successfully updated customized icon association for Application:[$ApplicationName]."
           
        }
        Write-Host "Error in associating customized icon for Application:[$ApplicationName] $_"
        
    }
    Write-Host "Successfully associated customized icon for Application:[$ApplicationName]."
  }

  end {
    [System.gc]::collect()
  }
}



Function AddIconToApp($a) {

    foreach($Item in $a)
    {
        $IconFile = $IconFolder+"\"+$Item.DisplayName+".png"
        if (!(Test-Path $IconFile)) { 
            $IconFile = $IconFolder+"\"+$Item.DisplayName+"-0.png"
        }
        Write-Host Trying $IconFile
        if (Test-Path $IconFile) { 
            Write-Host "Adding Icon to" $Item.DisplayName
            $ItemName = $Item.Name
            HVApplicationIcon -ApplicationName $ItemName -IconPath $IconFile -ErrorAction SilentlyContinue
        } else {
                Write-Host "File Doesn't Exist"
        }  
        
    }
}


$dir = Get-Location

$IconFolder = $dir.Path + "\png"


Connect-HVServer $h -u $u -p $p

$csv = Import-Csv .\$c

AddIconToApp $csv

Disconnect-HVServer -Server * -confirm:$false