PowerShell: Citrix XenApp Commands, Copying HMR Tests

Intro

Your Citrix farm will have the Health Monitoring and Recovery Tests turned on for all servers by default.  I have found that some tests can cause problems in the daily operation of your farm.  In particular, the XML Service Test will take your XenApp servers out of production since its default action is to remove the server from load balancing if the test fails. Typically you have to run the following command to discover if you have any servers removed this way (unless you love watching the alerts section in the AMC):

QFARM /LBOFF

This command will place the server (CTXSERVER1) back into load balancing:

ENABLELB CTXSERVER1

My advice is to only run the XML Service Test on the servers you have dedicated to XML ticket requests, and if you happen to have a NetScaler I would manage your XML load balancing with it instead of using the HMR tests.  In this post, I will cover some XenApp PowerShell cmdlets that will allow you to remove this test from all the servers in your farm.

PowerShell

First, get your current HMR tests and save them in a variable (NOTE: You should have the Citrix Cmdlets loaded):

Add-PSSnapin -Name Citrix.XenApp.Commands
$HMRTests = Get-XAHmrTest

Which gives us:

PS C:\>$HMRTests
TestName : Citrix IMA Service test
Description : This test queries the service to ensure that it is running by enumerating the applications available on the server.
FilePath : Citrix\IMATest.exe
Arguments :
Interval : 60
Threshold : 5
Timeout : 60
RecoveryAction : AlertOnly
ServerName :

TestName : Logon Monitor test
Description : Logon/logoff cycles are monitored to determine whether there is a problem with session initialization or possibly an application failure. If there are a lot of short cycles within a short time period, a problem is assumed to exist
FilePath : Citrix\LogonMonitor.dll
Arguments : /SessionTime:5 /SessionThreshold:50 /SampleInterval:600
Interval : 1
Threshold : 5
Timeout : 1
RecoveryAction : AlertOnly
ServerName :

TestName : Terminal Services test
Description : This test enumerates the list of sessions running on the server and the session user information, such as user name.
FilePath : Citrix\CheckTermSrv.exe
Arguments :
Interval : 60
Threshold : 5
Timeout : 30
RecoveryAction : AlertOnly
ServerName :

TestName : XML Service test
Description : This test requests a ticket from the XML service running on the server and prints the ticket.
FilePath : Citrix\RequestTicket.exe
Arguments :
Interval : 60
Threshold : 5
Timeout : 60
RecoveryAction : RemoveServerFromLoadBalancing
ServerName :

So we have an object-array full of the HMR tests, but we don’t want the last one, namely the XML Service Test. I’m going to create a new object array variable that will only hold the first 3 objects in $HMRTests.

$HMRNewTests = $HMRTests[0..2]

The default Farm Properties for the Heath Monitoring and Recovery are to Use Farm Settings.

image

Server Properties:

image

In order to turn this off you can use the following command:

Get-XAServer -ServerName CTXSERVER1 | Set-XAServerConfiguration -HmrUseFarmSettings $false -HmrEnabled $true

This changes the server properties to:

image

Now you just have to copy the HMR Tests to the server with this command:

$HMRNewTests | New-XAHmrTest -ServerName CTXSERVER1

Now the server properties shows the new tests without the XML Service Test:

image

Using these commands you can make the changes to all the servers in your farm at once, but please test in a development environment first and use the handy –whatif flag on your commands to confirm the changes are what you intend.

As always, I welcome all comments and questions (especially about a better way to do this with PowerShell).

Thanks,
Alain

Advertisements

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