PowerShell: Forcing ICA Memory for Session Graphics higher than 8192k

Windows PowerShell
Image via Wikipedia

Intro
In our XenApp environment, we support a desktop running dual 22” screens at a resolution of 1680×1050 (which is the standard desktop at work).  We can use a simple formula to calculate the amount of session graphics memory we need to support this screen setup.

Session Graphics Memory Calculation Table

X Width of the ICA session window
Y Height of the ICA session window
Z Color Depth of the ICA session window
(1-8 bit, 2-16 bit, 3-24 bit)
M Session Graphics Memory Required
Formula M=X*Y*Z

Default LCD Screen Resolutions:

Standard Widescreen
17″ – 1024 x 768 19″ – 1280 x 1024
19″ – 1280 x 1024 22″ – 1680 x 1050
24″ – 1920 x 1200

Calculating Dual 22” screens at 1680×1050 = M = (2 * 1680) x 1050 x 3 = 10584000 or 10,584k

The exceeds the standard size for XenApp Session graphics which is 8,192k.  Citrix outlines how to change this setting in a server’s registry in CTX114497.  We found, however, that after we set this value, XenApp would set it back to the standard size.

PowerShell to the rescue
It turns out that the permissions were not set correctly on the registry key.  You have to explicitly deny SYSTEM the ability to SETVALUE on the key, otherwise the system changes the ICA Session Graphics back to the default farm settings.  The current method (Res Wisdom) we used to set the value did not have enough granularity to properly set the registry key permissions.

A quick Google search struck pay dirt in an on-line eBook by no less a PowerShell luminary than Dr. Tobias Weltner.  Using this as a reference: http://powershell.com/cs/blogs/ebook/archive/2009/03/30/chapter-16-the-registry.aspx#permissions-in-the-registry, I wrote 2 PowerShell routines to manipulate the permissions on this key.

The first removes DENY permissions for the SYSTEM account, which in our case allows Res Wisdom to change the setting if needed (Wisdom uses SYSTEM to change/query registry settings).

# =========================================================================================================================
# AUTHOR: Alain Assaf
# NAME:   unset-permissions-icawd.ps1
# DATE:   7/26/2010
#
# SOURCE: http://powershell.com/cs/blogs/ebook/archive/2009/03/30/chapter-16-the-registry.aspx#permissions-in-the-registry
# COMMENT: Resets HKLM key below to allow for permission inheritance so value can be set by SYSTEM
# =========================================================================================================================

# Create $acl and point to registry key
$acl = Get-Acl "hklm:\system\currentcontrolset\control\terminal server\wds\icawd\thin16"
$acl.SetAccessRuleProtection($false, $true)
Set-Acl "hklm:\system\currentcontrolset\control\terminal server\wds\icawd\thin16" $acl

# Remove Deny on SetValue for SYSTEM:
$person = [System.Security.Principal.NTAccount]"SYSTEM"
$access = [System.Security.AccessControl.RegistryRights]"SetValue"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Deny"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule($person,$access,$inheritance,$propagation,$type)
$acl.RemoveAccessRule($rule)
Set-Acl "hklm:\system\currentcontrolset\control\terminal server\wds\icawd\thin16" $acl

# Remove Deny on FullControl for SYSTEM:
$person = [System.Security.Principal.NTAccount]"SYSTEM"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Deny"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule($person,$access,$inheritance,$propagation,$type)
$acl.RemoveAccessRule($rule)
Set-Acl "hklm:\system\currentcontrolset\control\terminal server\wds\icawd\thin16" $acl

The second runs after the registry settings are set and re-establishes the proper permissions to let SYSTEM read the key, but not change it.

# =========================================================================================================================
# AUTHOR: Alain Assaf
# NAME:   set-permissions-icawd.ps1
# DATE:   7/26/2010
#
# SOURCE: http://powershell.com/cs/blogs/ebook/archive/2009/03/30/chapter-16-the-registry.aspx#permissions-in-the-registry
# COMMENT: Sets proper permissions on hklm:\system\currentcontrolset\control\terminal server\wds\icawd\thin16
#          to allow for dual 22" screens for XenApp users.
# =========================================================================================================================

# Create $acl
$acl = Get-Acl "hklm:\system\currentcontrolset\control\terminal server\wds\icawd\thin16"

# Grant Administrators get Full Control:
$person = [System.Security.Principal.NTAccount]"Administrators"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule($person,$access,$inheritance,$propagation,$type)
$acl.ResetAccessRule($rule)

# Grant Users Read Access:
$person = [System.Security.Principal.NTAccount]"Users"
$access = [System.Security.AccessControl.RegistryRights]"ReadKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule($person,$access,$inheritance,$propagation,$type)
$acl.AddAccessRule($rule)

# Grant SYSTEM gets Full Control...
$person = [System.Security.Principal.NTAccount]"SYSTEM"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule($person,$access,$inheritance,$propagation,$type)
$acl.AddAccessRule($rule)

# ...except for SETVALUE:
$person = [System.Security.Principal.NTAccount]"SYSTEM"
$access = [System.Security.AccessControl.RegistryRights]"SetValue"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Deny"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule($person,$access,$inheritance,$propagation,$type)
$acl.AddAccessRule($rule)
$acl.SetAccessRuleProtection($true, $false)

# Apply new ACL on registry key
Set-Acl "hklm:\system\currentcontrolset\control\terminal server\wds\icawd\thin16" $acl

Now XenApp cannot change this setting and it sticks upon subsequent reboots or changes to the XenApp farm settings.

Thanks,
Alain

Stupid Citrix Tricks – 1

We are currently working on a project to move from published applications to published desktops.  With all the logistical issues and complications to make this experience as smooth as possible, one silly annoyance cropped up.  When you log into a Citrix desktop via ICA you may see this:

ICA Login to XenApp Server
ICA Login to XenApp Server

Typically, you don’t want to have your users see this because then the seemless desktop experience is a little tarnished.  There are a variety of ways to solve this problem, but the eaisest is to demonstrate your mad MSPaint skills.

On your XenApp system, look for ica256.bmp and ica.bmp under C:\Program Files\Citrix\System32.  All you have to do is open these files up and color them one solid color.  Once you do this, your users will see this:

ICA Login to XenApp Server modified
ICA Login to XenApp Server modified

Voilà, now your users hopefully won’t notice that something is different.  Of course, that Windows 2003 Login may be a dead give away.

Thanks,
Alain

Creating a Green Dashboard – Part 2

In the first part of this series, we covered gathering data on external users and how to parse that data into a database.  To generate the data to show how your Citrix farm positively impacts the environment and quality of life for your teleworkers, you need to get the average statistics for them.  Governments gather this data as it pertains to their own telework programs.

The U.S. government site, telework.gov, provides a one-stop-shop for general information, but no hard data except for number of participants at the various agencies.  We need a site that will give us savings on money, fuel, and pollutants. 

The Telework Exchange has a lot of papers and studies, and it provides statisics for yourself, based on location and miles driven.

The most detailed information I’ve been able to find so far, is the Undress4Success site.  This site has quite of bit of information as well as links to job boards and details of “work at home” scams.  They also have done a lot of the work of analyzing many telework studies and making it available to visitors.

For this example dashboard, I’ll track gas saved and green house gas savings.

For gas saved in my geographic area, this is 2,847,724 gallons saved per year or approximately 177 gallons per teleworker (16,058) or roughly 0.50 gallons saved per person/per day teleworking.

Following the same method for greenhouse gases, 26,991 metric tons are saved annually.  Using Google to convert this to pounds, gives us 59,504,969 pounds saved.  This breaks down to 10 pounds saved per person/per day teleworking.

Using these amounts to start with we can show the amount of gas and greenhouse gas emissions someone is saving per day when they use our Citrix farm.   This is just a starting point, we could expand this to other cost savings for the teleworker and for the company as well which I’ll cover at the end of this series.