Tag Archives: Res Wisdom

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

Advertisements

Wisdom-Fu: E-mail Alert when your TS logins are disabled

Introduction

XenApp server maintenance is a necessary part of managing a Citrix farm (unless you are using Provisioning Services?).  We use Wisdom (which I will detail in a later post) to perform an elaborate, reoccurring maintenance reboot job on our servers.  Part of the maintenance job is to disable Terminal Server logins when the job starts and enable them when the job completes.  Naturally, Murphy’s Law is in effect all the time when it comes to Citrix servers, so the maintenance job will not complete on a couple of servers and they will have their logins disabled when users start to login.  For this post, I’m going to detail a simple Wisdom module that you can schedule to run ‘in the morning’ that will send you an e-mail alert for any servers that have their logins disabled.


Wisdom Module Overview

The module consists of 2 actions:

image

With these module parameters:

image

  • SERVERNAME will be set to the %COMPUTERNAME% environment variable of the server the module is run against.
  • SecurityContext is used for the E-mail task
  • LoginsDisabled is a conditional parameter that we use to determine whether to send an e-mail or not.

Wisdom Module Detail

Query Registry Settings

The first task simply examines the WinStationsDisabled value for the following registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon

If the value is 1, then we’ll set our Wisdom parameter LoginsDisabled to 1, otherwise, it is 0.

image

Send E-mail

The second task runs if the LoginsDisabled parameter is equal to 1, otherwise skip this task.

image

Here are the e-mail settings so you can see how the SERVERNAME parameter is used:

image

Building block available here.  You can also follow more discussion at the Res Software User Group forums.

Thanks,
Alain

Wisdom-Fu: E-mail alert when you find a memory dump

Res software is probably best know for their PowerFuse product which provides powerful and granular control of a system and a user’s environment.  They also have a terrific product called Wisdom which they describe as “Run Book  Automation for Windows.”  We utilize Wisdom every day to manage our XenApp farm and related servers.  I could spend pages and pages gushing about Wisdom, but I’m going to use this post to show how I use Wisdom to accomplish certain tasks. Naturally, the solution I present can be accomplished in a variety of ways, but I find Wisdom to be elegant and have a very short learning curve.  On top of that, it provides extensive,detailed change management and reporting which many products to not.

Scenario

Typically, a XenApp environment has many, many variables at work that can compromise the stability of a system.  At times, this results in a crash dump and reviewing these dumps can give insight to what caused the problem.

NOTE: If you have a affinity for punishing yourself and want to actually dive into dumps, I highly recommend Crash Dump Analysis by Dmitry Vostokov.  Check out his minidump analysis series to get started.

In our environment, we have many servers and occasionally one will crash, reboot, and come back into production before we get an e-mail alert and we would not know if a dump was generated unless we connected to the server to find it.  I will describe how I created a Wisdom module to detect dump files on a server, copy them to a central location, and send an e-mail alert to the team.

Step 1 – Determine if a dump file exists

You can set up your server to create full and mini dumps by going into Computer properties, clicking the Advanced tab, and selecting Startup and Recovery.

image

This window will show you where the dump files are being created. Full memory dumps are written to: %SystemRoot%\MEMORY.DMP and minidumps are written to: %SystemRoot%\Minidump\

Here is the Wisdom Module that we’ll dive into:

image

The Execute Command task:

image

The command line is: if not exist %WINDIR%\Minidump\*.dmp EXIT /B 1

This is a conditional statement that looks for any file with a *.DMP extension in the Minidump directory.  If the file exists, then the command will successfully end with an error code of 0 (as set by Wisdom) otherwise it will fail and exit with an error code of 1.

Step 2 – E-mail someone that a memory dump file was found

The send e-mail task

image

I’m highlighting the Condition portion of this task because this is where the conditional logic of the previous task (and its exit codes comes into play).  The condition is whether the previous task was successfully completed.  If so, the we set a DUMPEXISTS parameter to 1 if true or 0 if false.

Step 3 – Copy the memory dump to a network share and off the server

The perform file operations task

image

The task creates a directory on a share (based on the server name – more on this later), copies the memory dump file to that location and then deletes it from the server.  The condition on this task is the value of DUMPEXISTS, which we set in the previous task.  If the e-mail task ran, then DUMPEXISTS is set to one, so this task will run and move the dump to a network share.

The remaining 3 tasks for this module repeat the previous 3 for the other memory dump type.

Wrapping Up

The SERVERNAME parameter (which is used when we copy the memory dump to the network) is simply formed by the %COMPUTERNAME% variable.  Wisdom, luckily, has access to the environment variables that are set on the machine the task is run on.

image

Finally, you should set this module to run on every reboot, then you’ll get e-mail alerts that memory dumps were generated if a server crashes.

Building Block

Wisdom allows you to export any resource, module, project or run book as an XML file that can be imorted to another Wisdom database.  Another wonderful feature.  I’ve sanitized a building block of this module for the community.  Due to WordPress file extension restrictions, I’ve renamed the building block with a .DOC extension.  Change it to .XML and you should be able to import it.

module_get dmp files if they exist

Thanks,
Alain