The game in Application Streaming is “profile once”, “run many”. The Streaming Profiler captures stuff at profiling time and stores it someplace that it can be referenced at execution time. This post describes the format of the “stuff”. “Describes it” is a loose statement of documenting the format because it isn’t exactly “hidden” from the get go. Having a written description though can be useful when looking at the content stored on your Application Hub.
The stuff stored on the file server (Application Hub) is two portions:
1) A profile contains a list of applications, by name along with a list of icons, by image. Combine that together with the location of the Application Hub and the name of the profile and you have EVERYTHING you need to publish an application. The “profile layer” contains only the publishing data. Notice that the Citrix Access Management Console which publishes applications in XenApp needs to look only at the “profile layer”, this is on-purpose. You can publish a single icon and later implement multiple execution methods to execute that application, for example, 32 and 64 bit versions of the application. Publish once! Less icons, less publishing.
2) One or more execution targets. The targets contain only the stuff needed to RUN the application and a profile may contain multiple execution targets, though fewer is preferred. For convenience, everything associated with the target is contained inside a CAB container file, but the execution stuff is extracted to non-compressed space where it is accessed for execution. This run time extraction occurs only once for the life of a target and the extracted content is shared across all users on a XenApp server side execution. This means that only one user pays the “first launch penalty” and even that can be pre-performed. The targets are named with GUID_version.cab and that naming exercise is outlined in excruciating detail, here.
Each profile is stored in its own directory; generally beneath a common “profiles” or “packages” directory on the Application Hub. Each profile gets its own directory to simplify copying and maintenance of the profile content. This also makes it easier to restrict access rights so that only the users who are published, can see the application profile. Active Directory groups are very useful for this common publishing/access management. Keeping them all in a same general location also makes it possible to have relative references between the profiles and this is exploited in Inter-Isolation Communication, so that links can be established without having to code non-portable paths to other profiles, handy.
Files that exist at the PROFILE layer
XML formatted text file which is the “TOP” file of everything about the profile and all of its execution targets. The “properties” of a profile that you can edit in the streaming profiler are all stored inside this XML file. You COULD edit them via manual XML edit, but I would not recommend that as a practice. The profile includes information about the applications that can be published and pointers to the icon data described later in this post. For entertainment, copy the profilename.profile to profilename.XML and then load into Internet Explorer or Firefox for syntax assisted viewing. You can see “secret stuff” beyond what the profiler GUI shows you, such as the version data of the streaming profiler that was used to create the profile or to most recently modify a target.
Binary file holding bits which represent all of the icons of every application installed into every target of the profile. The Applications at the profile layer are a “set union” of all of the applications of all of the Targets. Likewise, the icons at the profile layer are the “set union” of all of the icons of all of the applications of all of the targets. Notice that Targets do not store icons as icons are not needed for execution. The format of the icon data is binary. There is no API in Windows to “convert this HICON to binary”, or to extract all the icons from this file and store them where I can get to them later in a screen resolution that is right on the machine that I will be running on then rather than the machine that I am running on now. The streaming profiler/client pull this off and doing that along with upgrading color depth to 32-bit means that icons file format is an area ripe for change. We have changed the format of the icon data 3 times that I can recall. To get to the bits, use Profiler SDK (bottom of post).
SHA1 cryptographic hash of every file at the profile layer. sha1 = rich man’s CRC. More details on these in target section. At concept, this file is the “key” to Digital Signature. The profile XML data can be digitally signed and inside that file is a hash of the hashes. The hashes has a hash of all of the files of the profile/target and all of this flows downhill to assure the streaming client that the content it is pulling off of the Application Hub is the SAME content that the signing administrator put there. Neat stuff!
One or more CAB files which hold the execution content, the Target. On the development team, we all rather wanted a container file. A single file makes pre-deployment an atomic test. Do I have it? The answer is yes, or no, but never “maybe”. This simplifies pre-deployment, but looking back it wasn’t critical to have a container. An important point: the CAB file is NOT compressed using the default Windows utilities. Those would cause the whole CAB file to change on a single file update and would make the action of pulling a single file out of the cab file slow.
Scripts (sub directory)
Subdirectory holding all “scripts” defined at the profile level. Scripts are not text, they are binary. Anything can be a script including textual bat files, executable content such as .EXEs and even “data”. Though that last one should be marked as “disabled” so that the streaming client doesn’t attempt to “execute it”.
TARGET FILES (Stuff inside the CAB)
When browsing profile content using Windows Explorer, after opening the CAB file, sort by PATH. All of the important stuff will be at the top (root of the CAB).
Font’s captured during profiling that are accessed during execution
This file appears to be textual as it has a .TAB extension, but it is binary. The .TAB file contains the “registry” content of the installed/profiled application captured during profiling. In early development of Application Streaming, we actually used .REG files for this intermediate storage. The content of the .TAB file is the same as a .REG file, except the hard coded paths common to .REG files are replaced with “relative” path storage and the registry content is converted to binary for efficient access. I have previously described how to extract the registry content.
The calculated hashes were originally to be used only to support digital signature of the entire profile (which is optional). They work out to be really handy for other purposes. Having these from version 1 to version 2 of a target upgrade lets the streaming client know which files, among potentially thousands, are the same from version to version, without even looking at the server side version of the files. This is so time efficient that the hashes are calculated and used even if the profile will not be digitally signed. I say efficient because the streaming client can “know” that a server side version of a file is the “same as it was” based on a 4 byte in memory compare! Good stuff for the bit heads in the crowd.
The TARGET level hashes file also stores the file date, time, size, attributes and everything else associated with directory enumeration. The contents of this file are what is used to respond to directory enumeration at execution, for the files that “aren’t there”.
Yes, sha1 hashes can be a beast to calculate during profiling. A high percentage of the time that passes during “finalizing your package” is spent calculating these hashes. The other large portion is spent creating the CAB file. The theory is that time spent in profiling is less important than time spent by the users, so the hashes are calculated, always.
The streaming client consults this file and will extract the given files before launching the to be run application. IMHO, this file is bogus and should not exist, but back in the day I lost that battle. I am pleased though that a current inspection of a “fresh” profile has this file created, but empty. This means it will still be compatible with “older” streaming clients, but gets back to having no purpose.
In the early days, this file held the short filenames that go with files that also have long filenames. This is to support applications that use only short filenames at runtime and absolutely insist that the profiling time (install time) and runtime short filename be the same name. The most demanding offender here is the MSI installer service itself, which is interesting to ponder as you would think that the MSI installer could handle long filenames.
In the modern days, the contents of SFN.txt have been moved into the end of the per-file entry on hashes.txt. This means that SFN.txt is a legacy that exists today only to support “older” streaming clients (backward compatibility).
Another XML formatted file. This one holds the “rules” which govern isolation. All of the “isolate”, “ignore”, “redirect” and “strictly isoalte” rules are defined in this file. You can see the “default” rules by looking at the installation directory for the streaming client on your system. The Streaming Profiler reads the installed version of this file to define the default rules for all created profiles. Then, any runtime defined rules get added along with any rules that the administrator defines using the GUI of the streaming profiler. The Targets rules are stored “with the Target” so that it’s rules are “steady” even if a new version of the profiler is installed.
Represents the installation file system content for the captured installation. It is a grand mystery why the AIE/Rade FSFD stores “Device” in the name of the captured file content. In a perfect world, this would be replaced with just “drive letter” or even better, “boot drive”.
More details than you probably ever wanted to know. But, there it is. Please don’t become too dependent on the specific format; we do not promise that it won’t change. If you want to change things in the profile or even look at it programatically, the RIGHT method is to use the streaming profiler SDK to get to the bits. Really! Use the SDK! It insulates you from the format. Knowing what the native bits are though, can be useful.