Skip to content

Instantly share code, notes, and snippets.

@Nillth
Created May 24, 2025 01:36
Show Gist options
  • Save Nillth/273b3fbdd70ac563e042fb6f3ede3f65 to your computer and use it in GitHub Desktop.
Save Nillth/273b3fbdd70ac563e042fb6f3ede3f65 to your computer and use it in GitHub Desktop.
<#
.NOTES
===========================================================================
Created by: Marc Collins
Organization: Qlik Customer Success
Email: [email protected]
Filename: QlikSenseSDK_Update_AppTheme.ps1
===========================================================================
.DESCRIPTION
Update the App Theme for one or more Qlik Sense Apps
#>
# Set the current location to the script directory
Push-Location $PSScriptRoot
# Import the modules and binary files
Import-Module '.\bin\QlikSenseCLI'
Add-Type -Path '.\bin\Newtonsoft\Newtonsoft.Json.dll'
Add-Type -Path '.\bin\QlikSenseSDK\16.4.0\Qlik.Engine.dll'
Add-Type -Path '.\bin\QlikSenseSDK\16.4.0\Qlik.Sense.JsonRpc.dll'
Add-Type -Path '.\bin\QlikSenseSDK\16.4.0\Qlik.Sense.Client.dll'
# Get the Qlik Client Certificate
$QlikClientCertificate = Get-ChildItem Cert:\CurrentUser\My\ | Where-Object {
$_.Subject -eq 'CN=QlikClient'
}
# We can use the current system as the hostname, or we can extract from the Issuer of the QlikClient
#$QlikServerHostName = $QlikClientCertificate.Issuer.Substring(($QlikClientCertificate.Issuer.IndexOf('=') + 1), ($QlikClientCertificate.Issuer.LastIndexOf('-CA') - ($QlikClientCertificate.Issuer.IndexOf('=') + 1)))
$QlikServerHostName = $env:COMPUTERNAME
# Set the user account to connect as (sa_api is usually a good choice)
$UserDirectory = 'Internal'
$UserID = 'sa_API'
# Connect to QlikSense QRS
$QRSClient = Connect-QlikSense -TrustAllCertificates -Certificate $QlikClientCertificate -Username "$($UserDirectory)\$($UserID)" -Passthru -Hostname $QlikServerHostName
#region Generate ThemeList and Select Theme
$Themes = [System.Collections.Generic.List[string]]::new()
#This is not ideal, but I have not figured out how to access the Capability APIs' to get the real list, so we will create from other sources.
#Get Default Theme List
$defaultthemes = Invoke-QSGet -QlikClient $QRSClient -Path "$($QRSBaseURI)/resources/assets/external/sense-themes-default/default-themes.json" -Raw | ConvertFrom-Json
$Themes.AddRange([string[]]$defaultthemes.default.id)
# Add the missing one
$Themes.Add('horizon')
#Get Any Imported Themes
$QSExtension = Get-QSExtension -QlikClient $QRSClient -Full
$Qexts = $QSExtension.References.ExternalPath | Where-Object {
$_.EndsWith('.qext')
}
$QRSBaseURI = "$($QRSClient.URLQRS.Substring(0, $($QRSClient.URLQRS.LastIndexOf('/'))))"
$ExtensionInfo = foreach ($Qext in $Qexts)
{
Invoke-QSGet -QlikClient $QRSClient -Path "$($QRSBaseURI)$($Qext)" -Raw | ConvertFrom-Json
}
$ExtensionThemes = $ExtensionInfo | Where-Object {
$_.type -eq 'theme'
}
if (($ExtensionThemes | Measure-Object).count -gt 0)
{
$Themes.AddRange([string[]]$ExtensionThemes.name.ToLower())
}
$SelectedTheme = $Themes | Out-GridView -OutputMode Single -Title 'Theme to apply'
#endregion Generate ThemeList and Select Theme
if ($null -ne $SelectedTheme)
{
# Set the Engine URL from the info retrieved from QRS
$Location = [Qlik.Engine.Location]::FromUri($QRSClient.URLQES)
$extendedSecurityEnvironment = $false
$certificateValidation = $false
# Authenticate to the Qlik Engine
$Null = $Location.AsDirectConnectionAsync($UserDirectory, $UserID, $extendedSecurityEnvironment, $certificateValidation, $QlikClientCertificate)
# Get All AppIdentifiers from the engine (Results limited by load balancing rules)
$AllAppIdentifiers = [Qlik.Engine.LocationExtensions]::GetAppIdentifiers($Location)
$Session = $Null
$noData = $false
$SelectedAppIdentifiers = $AllAppIdentifiers | Out-GridView -PassThru
# $AppIdentifier = $SelectedAppIdentifiers[0]
foreach ($AppIdentifier in $SelectedAppIdentifiers)
{
$QEApp = [Qlik.Engine.LocationExtensions]::App($Location, $AppIdentifier, $Session, $noData)
$AppInfo = $QEApp.GetAllInfos()
$AppProps = $AppInfo | Where-Object {
$_.type -eq 'appprops'
}
$QEAppProps = $QEApp.GetGenericObject($AppProps.Id)
$AppProperties = $QEAppProps.GetProperties()
# Generic Methods are a pain...
$AppPropObj = $AppProperties.GetType().GetMethod('As').MakeGenericMethod([Qlik.Sense.Client.AppPropertiesObjectProperties]).Invoke($AppProperties, $null)
#Once we have the AppPropertiesObject We can set the properties such as Theme and colours
Write-Host "$($AppIdentifier.AppId): $($AppIdentifier.AppName)"
Write-Host "Replacing: $($AppPropObj.Theme) with $($SelectedTheme)"
$AppPropObj.Theme = $SelectedTheme
#$AppPropObj.SheetTitleBgColor = '#8e477d'
#$AppPropObj.SheetTitleColor = '#4477aa'
$QEAppProps.SetProperties($AppPropObj)
$QEApp.SaveObjects()
$QEApp.Dispose()
}
}
Pop-Location
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment