Creating a custom template for Citrix Optimizer

Do you optimize your image? If not, you should! Citrix Optimizer is THE optimization tool for Citrix workers, created by Citrix for Citrix customers. The default templates included in Citrix Optimizer are pretty solid, but creating a custom template for Citrix Optimizer is an option as well. This article explains how to create these.

Note:
Version 2 of the Citrix Optimizer will include a GUI to create custom templates. Version 2 will be available latest in Q1 2019. Follow it's developer Martin Zugec on Twitter to catch the latest announcements.

Table of Contents

Introduction

First of all, if you are not familiar with Citrix Optimizer, please check out the following links:

You may wonder why there is a need to create custom templates. Doesn't the Citrix Optimizer already include all necessary optimizations? The truth is that no optimization tool can ever include everything you may require in your organization. This would be an unfair expectation of any tool. What is a valid expectation though is to be able to create your own custom templates so you can add your own customizations. You can customize Citrix Optimizer by modifying the underlying XML files.

This article was written for Citrix Optimizer version 1.2.0.67. As I mentioned in the beginning of this article, version 2.x of Citrix Optimizer will include a GUI that will make customizations more administrator-friendly. For now, the only way how to create custom settings is by directly modifying the underlying XML files.

An overview of Citrix Optimizer

Citrix Optimizer consists of three main parts:

  • The main engine CitrixOptimizer.exe and CtxOptimizerEngine.ps1.
  • The PowerShell module files located in the subdirectory Modules.
  • The template files (*.xml) located in the subdirectory Templates.

Log files are written to the subdirectory Logs.

The screenshot below shows the Citrix Optimizer directory structure, highlighting the directory where the XML templates are stored.

Creating a custom template for Citrix Optimizer - Citrix Optimizer folder structure

When the GUI of the Citrix Optimizer (CitrixOptimizer.exe) is launched, it lists all available XML files found within the Templates directory:

Creating a custom template for Citrix Optimizer - Citrix Optimizer screenshot

Any custom XML you add to the Templates directory is listed automatically by Citrix Optimizer:

Creating a custom template for Citrix Optimizer - Citrix Optimizer with custom template screenshot

You do not even have to close the application to refresh the list of templates. In case you copied a new template to the template directory after Citrix Optimizer was already launched, simply click somewhere in the GUI, for example Recent Files and than back to Templates to see the new template appear in the list.

An overview of a Citrix Optimizer template

Citrix Optimizer templates are XML files. One XML file equals one template.

Creating a custom template for Citrix Optimizer - Templates directory contents

These files can be opened in any text editor, for example in Notepad. The XML structure is build-up as follows:

1. A header section

The header section, among other items, includes the display name of the template (which is visible in the GUI):

Creating a custom template for Citrix Optimizer - GUI title and info button

Other information included in the header section are the description of the template (shown when hovering over the information icon), the name of the vendor and a version number.

Creating a custom template for Citrix Optimizer - XML template header

2. One or more groups.

Groups represent the main categories in a template. The display name of a group is what you see in the left pane in the GUI.

Creating a custom template for Citrix Optimizer - GUI groups

Creating a custom template for Citrix Optimizer - XML template groups

The group ID is the short name of the group. This short name is used when running Citrix Optimizer using PowerShell (as opposed to the GUI) and you only want to optimize settings included in specific groups, for example:

3. One or more entries in a group

Entries represent the individual optimizations within one group. One entry equals one optimization.

Creating a custom template for Citrix Optimizer - GUI entries

Creating a custom template for Citrix Optimizer - XML template entries

Multiple entry types exist. These are explained in detail in the section Create a custom entry in this article.

Creating your own template

The easiest way how to create a custom template file is by copying an existing one and than do some reverse engineering. When choosing an existing template to use as your base line, make sure to select one for the same operating system as you intend to optimize. Technically it is possible to create a custom XML file that can be used for multiple operating systems, but you have to make sure that all settings included in the template apply to all of these operating systems.

The screenshot below shows the default templates including one additional (custom) template: Citrix_WindowsServer2016_1607_My_Custom_Template.xml.

Creating a custom template for Citrix Optimizer V1 - Citrix Optimizer custom template in template folder

As you can guess by the name, this custom template is a copy of the original template for Windows Server 2016 version 1607, Citrix_WindowsServer2016_1607.xml.

After copying an existing template you will have to make some adjustments in the various sections. All necessary customizations are explained in the remainder of this article.

Create a custom header

The first thing you want to do after you copied an existing template as your baseline is to change the header information:

Creating a custom template for Citrix Optimizer - XML template header 2

  • Section <metadata>:
    • Enter a descriptive display name between the tags <displayname> and </displayname>. This name is visible in the top of the GUI (as shown in the screenshot below.
    • Enter a description between the tags <description> and </description>.
  • Section <pack>:
    • Change the vendor so it is clear this template was not created by Citrix. The name of the vendor is placed between the tags <vendor> and </vendor>.
    • Enter a descriptive name between the tags <name> and </name>.
    • Enter a version between the tags <version> and </version>.
    • Enter a description between the tags <description> and </description>.

Creating a custom template for Citrix Optimizer - Custom name in GUI

Create a custom group

Most likely you will keep many of the existing optimizations from the original template. I recommend to create one or more custom groups that will include your custom optimizations, for example:

Creating a custom template for Citrix Optimizer V1 - Custom template open in Citrix Optimizer

A group is created using the tags <group> and </group>. A group also requires additional information such as the name of the group, a description and an ID:

  • The ID is placed between the tags <id> and </id>.
  • The display name is placed between the tags <displayname> and </displayname.
  • The description is placed between the tags <description> and </description>.

Creating a custom template for Citrix Optimizer - XML template header group

Create a custom entry

Each group requires at least one entry. An entry is where the action happens. This is where the optimization of one particular setting is configured. The easiest way how to create a new entry is by copying an existing one.

All entries have the following tags in common:

  • The name for the entry: <name></name>.
  • The description of the entry: <description></description>.
  • The execution mode of the entry: <execute></execute>.
  • The configuration/optimization: <action></action>.
  • The Citrix Optimizer plugin: <plugin></plugin>. There are multiple plugins available. These are described in more detail below.
  • The parameters in the section <params>. These are plugin specific parameters that are required to perform the action. You find more details concerning the various actions in the sections below.

The execution mode of an entry can either be 0 or 1. Zero means that the setting is optional: <execute>0</execute>.

Creating a custom template for Citrix Optimizer - Example of an optional setting

One means that the setting is mandatory: <execute>1</execute>.

Creating a custom template for Citrix Optimizer - Example of a mandatory setting

Multiple types of entries are available:

Custom entry for Services

The entry for services looks as follows:

The example above is the first service that is disabled in the default template for Windows Server 2016 version 1607 (Citrix_WindowsServer2016_1607.xml).

Enter the following variables to create this entry:

  • The name of the service (between the tags <name> and </name>). This can be any name you want. I recommend to use the display name of the server (e.g. AllJoyn Router Service as opposed to the service name AJRouter). The name can contain spaces.
  • The description of the service (between the tags <description> and </description>).
  • The execution value 1 (mandatory) or 0 (optional) between the tags <execute> and </execute>.
  • The name of the plugin to use (between the tags <plugin> and </plugin>). For services the name of the plugin is Services.
  • The name of the service (in the section <params> between the tags <name> and </name>). This has to be the service name and not the display name (e.g. AJRouter as opposed to AllJoyn Router Service).
  • The value of the action (= configuration of the service) in the section <params> between the tags <value> and </value>. Since we are working on optimizing the operating system the value should be Disabled.

This entry type automatically supports rollback when executed using PowerShell (as opposed to the GUI).

Custom entry for Scheduled Tasks

The entry for scheduled tasks looks as follows:

The example above is the first scheduled task that is disabled in the default template for Windows Server 2016 version 1607 (Citrix_WindowsServer2016_1607.xml).

Make sure to write down the name and location (= relative path in the scheduled task directory structure). You will need this later.

Creating a custom template for Citrix Optimizer - Scheduled task name and location

Enter the following variables to create this entry:

  • The name of the scheduled task (between the tags <name> and </name>). This can be any name you want. I recommend to use the actual name of the scheduled task though. The name can contain spaces.
  • The description of the scheduled task (between the tags <description> and </description>).
  • The execution value 1 (mandatory) or 0 (optional) between the tags <execute> and </execute>.
  • The name of the plugin to use (between the tags <plugin> and </plugin>). For scheduled tasks the name of the plugin is SchTasks.
  • The name of the scheduled task (in the section <params> between the tags <name> and </name>). This is the name of the scheduled task as shown in the screen shot above.
  • The relative path of the scheduled task (in the section <params> between the tags <path> and </path>). This is the location of the scheduled task as shown in the screen shot above. Any yes, the back slash at the beginning of the path should be included as well.
  • The value of the action (= configuration of the scheduled task) in the section <param> between the tags <value> and </value>. Since we are working on optimizing the operating system the value should be Disabled.

This entry type automatically supports rollback when executed using PowerShell (as opposed to the GUI).

Custom entry for Registry

Note: I added this section for the sake of completeness, but I strongly recommend to use an entry for PowerShell to modify registry values. Continue reading this paragraph for a more detailed explanation on this matter.

Citrix Optimizer version 1.2.0.67 contains a bug. When modifying a registry value without the actual registry value being present on the local system, Citrix Optimizer considers this setting optimized (although it is clearly not).

The structure of a default registry entry is as follows:

In case you want to remove a registry value completely you can use the value CTXOE_NoValue, like this:

Technically everything works fine; the registry value is indeed removed, but the GUI now claims that the item is NOT optimized.

Because of these issues I decided to use PowerShell to change registry values, because it gives me greater control.

I already talked to Martin Zugec, the developer of this tool, about this issue. This bug will be fixed in the next release.

This entry type automatically supports rollback when executed using PowerShell (as opposed to the GUI).

Custom entry for PowerShell (also used to modify the registry and to run executables)

The PowerShell plugin allows you to be very flexible in your customization. Let me explain how to use this plugin using some examples.

Please be aware that custom PowerShell functions do not support rollback at this time.

You can of course create any routine using PowerShell you require. I invite you to use the examples below to create your own customizations. If possible, it would be great if you could share these with the community.

PowerShell: set a registry value (e.g. disable Cortana)

In this example, we will disable Cortana by changing the corresponding registry value using PowerShell.

Add the following code to your custom Citrix Optimizer template if you want to optimize (disable) Cortana:

Most of the tags are the same as explained in the previous sections in this article, such as <name>, <description> <execute>, <action> and more. To be able to execute PowerShell code you have to use the plugin PowerShell. Add this between the tags <plugin> and </plugin>.

The section <executeparams> contains the code that will configure your optimization. Let's take a closer look at the PowerShell code.

In the first couple of lines we define some variables such as the registry key path, the registry value name, the registry value and the value type (e.g. DWORD or STRING).

Then we check whether or not the registry key exists. If not, it is created (New-Item). In case of an error, the error level is raised ($ExitCode++) and the Optimizer internal variable $Global:CTXOE_Result is set to $False to indicate the setting has not been optimized.

In the last section using the PowerShell cmdlet New-ItemProperty, the registry value is configured. In case there is no error, the Optimizer internal variable $Global:CTXOE_Result is set to $True to indicate that the setting has been optimized. Should an error occur the Optimizer internal variable $Global:CTXOE_Result is set to $False to indicate that the setting was not optimized.

The section <params> contains the code that checks the current configuration and determines whether or not the current configuration is already optimized or not. Let's take a closer look at the PowerShell code.

First we define the registry path, value name and required value.

Then, using a try / catch statement we retrieve the current value and store it in the variable $RegResult. In case the registry value does not exist the Optimizer internal variable $Global:CTXOE_Result is set to $False.
In case the value in $RegResult is equal to the value in the variable $RegValue, the setting is optimized ($Global:CTXOE_Result = $True). Otherwise, the setting has not yet been optimized and $Global:CTXOE_Result is set to $False).

PowerShell: rename a registry value (e.g. disable Active Setup)

Active setup runs at first user logon, but only within a published desktop. When starting a published application, Active Setup does not run. This is why it is a best-practice to disable Active Setup entirely. See Citrix CTP Helge Klein's article Active Setup Explained for more information.

The easiest way how to disable Active Setup is to rename both the 32-bit and 64-bit registry keys. Renaming the parent registry key automatically disables all individual Active Setup entries beneath it.

Original key names:

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components
  • HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Active Setup\Installed Components

Key names after being renamed (and thus disabled):

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\_DISABLED Installed Components_2018-11-10_10-24-11
  • HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Active Setup\_DISABLED Installed Components_2018-11-10_10-24-11

Add the following code to your custom Citrix Optimizer template if you want to optimize (disable) Active Setup 32-bit:

Add the following code to your custom Citrix Optimizer template if you want to optimize (disable) Active Setup 64-bit:

Most of the tags are the same as explained in the previous sections in this article, such as <name>, <description> <execute>, <action> and more. To be able to execute PowerShell code you have to use the plugin PowerShell. Add this between the tags <plugin> and </plugin>.

The section <executeparams> contains the code that will configure your optimization. Let's take a closer look at the PowerShell code.

In the first line we create a variable called $DateTime that includes the current date and time. We will use this later.

Now we define the new name for the registry key:

The fully qualified path of the registry key is set:

In the following part we test whether or not the original registry key exists. If not, this means that Active Setup has already been optimized (disabled). The Optimizer internal variable $Global:CTXOE_Result is set to $True, telling Citrix Optimizer that the setting has already been optimized.
In case the original Active Setup registry key exists, the key is renamed (Rename-Item). If this is successful, $Global:CTXOE_Result is set to $True. If for some reason renaming the key was not successful, $Global:CTXOE_Result is set to $False.
The Optimizer internal variable $Global:CTXOE_Details is used to report further details.

The section <params> contains the code that checks the current configuration and determines whether or not the current configuration is already optimized or not. Let's take a closer look at the PowerShell code.

Here we simply check whether or not the original Active Setup key exists. If yes, than Active Setup is not optimized (not disabled) and the Optimizer internal variable $Global:CTXOE_Result is set to $False. If the registry key does not exist than Active Setup already has been optimized; the Optimizer internal variable $Global:CTXOE_Result is set to $True.

PowerShell: run an executable (e.g. disable DEP using "bcdedit.exe")

It is a Citrix best-practice to disable Data Execution Prevention (DEP). See page 13 in the Citrix Windows 10 Optimization Guide.

You find DEP in the Control Panel under System \ Advanced \ Performance Settings \ Data Execution Prevention.

Creating a custom template for Citrix Optimizer - Data Execution Prevention

It is not possible to completely disable DEP in the GUI. This is only possible using the bcdedit.exe command.

Add the following code to your custom Citrix Optimizer template if you want to optimize (disable) DEP:

Most of the tags are the same as explained in the previous sections in this article, such as <name>, <description> <execute>, <action> and more. To be able to execute PowerShell code you have to use the plugin PowerShell. Add this between the tags <plugin> and </plugin>.

The section <executeparams> contains the code that will configure your optimization. Let's take a closer look at the PowerShell code.

The first line executes BCDEdit with the parameters /set nx AlwaysOff to disable DEP. The dot (.) in the beginning is necessary if you want to use a combination of environment variables and literal path.

In the second and third line two custom Optimizer variables are used:

The variable $Global:CTXOE_Result returns the result back to Citrix Optimizer. A value of $True means that the optimization was successful; a value of $False means that the optimization failed. The variable $Global:CTXOE_Details returns more details to Citrix Optimizer.

The section <params> contains the code that checks the current configuration and determines whether or not the current configuration is already optimized or not. Let's take a closer look at the PowerShell code.

First we need to enumerate the current BCDEdit configuration. The result is stored in the variable $BCDValue.

The information in the variable $BCDValue is not very readable so we need to split the result and store it in an array, removing any empty values.

Now we locate the value nx in the array and retrieve its array number. We know that the array item following nx is the actual value of nx, so we take the array number of nx and add 1 to get the array number of the value we are actually interested in.

Confused? Let me explain differently. Take a look at the screenshot below and locate the value nx. If the information below would be stored in an array and nx would be number 27 in that array, than the value OptOut would be number 28 in the array.

Creating a custom template for Citrix Optimizer - BCDEdit enumeration

The value of array number 28 (OptOut in our example) is what we are after. This value gets stored in the variable $BCDResult. The variable $BCDResult can contain one of four possible values: OptIn, OptOut, , AlwaysOff or AlwaysOff.

In the last two lines we determine whether or not DEP is optimized or not. In case the value store in the variable $BCDResult is AlwaysOff, DEP already has been optimized (disabled). In case it is any of the other three possible values than DEP is not optimized.

Conclusion

Creating your own custom template gives you more control over which settings are optimized. I invite you to share your experience with custom templates by leaving a comment below.

Share this post:
Dennis Span on EmailDennis Span on LinkedinDennis Span on Twitter
Dennis Span
Dennis Span
Dennis Span works as a Senior Citrix Architect for a large insurance company in Vienna, Austria. He holds multiple certifications such as CCE-V, CCIA and CCEA. In 2017, Dennis became a Citrix Technology Advocate (CTA). Besides his interest in virtualization technologies and blogging, he loves spending time with his family as well as snowboarding, playing basketball and rowing. He is fluent in Dutch, English, German and Slovak and speaks some Spanish.

4 thoughts on “Creating a custom template for Citrix Optimizer

Leave a Reply

Your email address will not be published.

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.