Self servicing DPI scaling while using RES ONE Workspace with Zero Profiling

Recently I worked on a XenDesktop project where RES ONE Workspace 2016 was implemented using Local Profiles and Zero Profiling on Windows 2012R2. End users wanted to be able to change the DPI scaling settings on demand within the Citrix session, as they were used to. This functionality was working for them because Roaming Profiles were being used. It is easy to capture these DPI settings using RES ONE Workspace, but applying them during user login using RES ONE Workspace has no effect. This is because these settings must be in place before the shell is loaded to get it to work.

One solution is to create a Active Directory GPO with GPP settings for the different DPI scaling settings and apply it by AD Group Membership. However, this would mean an increase of Servicedesk calls because end users would need to be put in the right AD group to have the DPI setting changed for them.

Therefore I decided to write a small AutoIt application to manage the DPI scaling settings so the end user can change it on their own. It works together with the Active Directory GPO GPP settings. Grab the AutoIt code at the end of this post!

How does DPI scaling work?

The DPI scaling factor is adjusted by setting two registry keys in HKCU\Control Panel\Desktop. These are Win8DpiScaling and LogPixels.

The DPI versus Scale ratio is 1,04166667. This results in the following values:

  • 96   – 100%
  • 120 – 125%
  • 144 – 150%
  • 192 – 200%

How does the DPI scaling application work?

In a nutshell, the application creates a text file in the users’ homefolder corresponding to the DPI scale choosen. At the next user logon it checks for the existence of this file in the users’ homefolder and applies the corresponding registry keys.

Start the application within a user session. On startup it reads the current DPI scaling setting from the user registry and displays it in the application.

Set DPI Scaling - General

Use the pulldown menu to select to desired DPI scale setting.

Set DPI Scaling - Options

Click Ok.

The application then creates a text file in H:\Personal Settings\DPI. The text file is named accordingly the DPI setting choosen(e.g. Scaling150.txt for 150% DPI scale). Earlier created Scaling text files in this directory will be deleted so only one DPI scale text file is available and used during next logon.

After that it asks you to log out of the system and log back in so the change can become active.

Set DPI Scaling - Message

When the end user starts up a new Citrix session the Active Directory GPO GPP setting comes into action. Upon login it checks for the existence of the created text file, and injects the needed registry key for the corresponding DPI scale.

And there you have it, giving back selfcontrol over the DPI scaling setting to the end users!

Set DPI Scaling - Enlarged

The needed registry keys

Needed registry keys

LogPixels

Item Level Targeting File Exists

The decimal values used for the DPI scales are:

  • 96   – 100%
  • 120 – 125%
  • 143 – 150%
  • 192 – 200%

Please note that Decimal value 143 is in fact corresponding to a DPI scale of 149%. I found that certain applications had issues running at 150% DPI scale. I figured that 1% off wouldn’t be noticed by end users :-).

This solution works on a Windows 2012R2 server. I have not tested it on Windows 10 and 2016.

Grab the code here. The application is built using AutoIt version 3.7.3. I’m no coding expert, but it get’s the job done. As always, test it in your own environment before taking it into production.

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <FileConstants.au3>
#include <File.au3>

Opt("GUIOnEventMode", 1) ; Change to OnEvent mode

; Here is the array
Global $aArray[4] = ["100%", "125%", "150%", "200%"]

; And here we get the elements into a list
$sList = ""
For $i = 0 To UBound($aArray) - 1
    $sList &= "|" & $aArray[$i]
	Next

; Create a GUI
#include <GUIConstantsEx.au3>
$hGUI = GUICreate("Set DPI Scaling", 400, 150)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton")
GUICtrlCreateLabel("Select the DPI scaling percentage and click Ok", 10, 50)
Local $iOKButton = GUICtrlCreateButton("OK", 120, 80, 60)
GUICtrlSetOnEvent($iOKButton, "OKButton")
GUISetState(@SW_SHOW, $hGUI)

; Read current DPI scaling from registry and show in Label
Local $CurrentDPI = RegRead("HKEY_CURRENT_USER\Control Panel\Desktop", "LogPixels")
If $CurrentDPI = "" Then
	$CurrentDPIPercentage1 = 100
Else
	$CurrentDPIPercentage1 = ($CurrentDPI) * "1.04166667"
EndIf
; Retrieve first 3 characters from the 1th position in the string.
Local $CurrentDPIPercentage2 = StringMid($CurrentDPIPercentage1, 1, 3)
GUICtrlCreateLabel("Current DPI scaling percentage:", 10, 20, 195, 20)
GUICtrlCreateLabel("%", 230, 20, 10, 20)
$CurrentDPILabel = GUICtrlCreateLabel($CurrentDPIPercentage2, 210, 20, 20, 20)

; Check for existing DPI Directory in Personal Settings, otherwise create directory
Local $sFilePath = "H:\Personal Settings\DPI"
Local $iFileExists = FileExists($sFilePath)
If $iFileExists Then
; Do nothing
Else
	DirCreate($sFilePath)
EndIf

Func DelScalingTXTFiles()
; Check for existing Scaling* .TXT files in H:\Personal Settings\DPI Directory. Delete them if any exist, otherwise skip section
Local $iFileExists2 = FileExists($sFilePath & "\Scaling*.txt")
If $iFileExists2 Then
; Add existing Scaling* .TXT files in Personal Settings\DPI Directory to Array and delete them
Local $sSourceFilePath = "H:\Personal Settings\DPI\"
$Array = _FileListToArray($sSourceFilePath, "Scaling*.txt")
For $i = 1 to $Array[0]
   FileDelete($sSourceFilePath & $Array[$i])
Next
Else
; Do nothing
EndIf
EndFunc   ;==>DelScalingTXTFiles


; Create the combo
$hCombo = GUICtrlCreateCombo("", 10, 80, 100, 20)
; And fill it
GUICtrlSetData($hCombo, $sList)

GUISetState()

While 1
	Sleep(100) ; Sleep to reduce CPU usage
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
		            Exit
				Case $hCombo

    EndSwitch
WEnd


Func OKButton()
    ; Note: At this point @GUI_CtrlId would equal $iOKButton,
	    ; and @GUI_WinHandle would equal $hMainGUI

							If GUICtrlRead($hCombo) = "" Then
								MsgBox($MB_OK&$MB_ICONWARNING, "Please select percentage", "You have not selected a scaling percentage. Please choose one and click Ok. This program will now exit.")
							EndIf
							If GUICtrlRead($hCombo) = "100%" Then
								Call("DelScalingTXTFiles")
								FileOpen("H:\Personal Settings\DPI\" & "Scaling100.txt", 1)
								MsgBox($MB_OK&$MB_ICONINFORMATION, "DPI scaling adjusted", "The screen settings have been changed. Please logoff and start a new session to use the new settings.")
							EndIf
							If GUICtrlRead($hCombo) = "125%" Then
								Call("DelScalingTXTFiles")
								FileOpen("H:\Personal Settings\DPI\" & "Scaling125.txt", 1)
								MsgBox($MB_OK&$MB_ICONINFORMATION, "DPI scaling adjusted", "The screen settings have been changed. Please logoff and start a new session to use the new settings.")
							EndIf
							If GUICtrlRead($hCombo) = "150%" Then
								Call("DelScalingTXTFiles")
								FileOpen("H:\Personal Settings\DPI\" & "Scaling150.txt", 1)
								MsgBox($MB_OK&$MB_ICONINFORMATION, "DPI scaling adjusted", "The screen settings have been changed. Please logoff and start a new session to use the new settings.")
							EndIf
							If GUICtrlRead($hCombo) = "200%" Then
								Call("DelScalingTXTFiles")
								FileOpen("H:\Personal Settings\DPI\" & "Scaling200.txt", 1)
								MsgBox($MB_OK&$MB_ICONINFORMATION, "DPI scaling adjusted", "The screen settings have been changed. Please logoff and start a new session to use the new settings.")
							EndIf
		Exit
EndFunc   ;==>OKButton


Func CLOSEButton()
    ; Note: At this point @GUI_CtrlId would equal $GUI_EVENT_CLOSE,
	    ; and @GUI_WinHandle would equal $hMainGUI
	;Un-comment next line if you want to show a reminder
	;MsgBox($MB_OK, "Reminder", "Please logoff and start a new session if you changed the screen settings.")
	    Exit
EndFunc   ;==>CLOSEButton
This entry was posted in Ivanti, Ivanti Workspace Control and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *