On Streaming and Formats in App-V
Tim Mangan
TMurgent Technologies, LLP
September 22, 2014
Related Product: App-V 5.0 SP2 HF5 and prior
When we created the original application virtualization product, SoftGrid, streaming was a very important part of the implementation. Over the years, the streaming aspect has become less important to implementations, while remaining important to the decision makers that choose application virtualization with App-V. What some may not realize is how App-V 5 changed how streaming is done from the previously generation product. This document identifies the differences and suggests that in most cases, streaming should not play such a large role in the decision to virtualize.
Historical Roots
Softricity, which created the original version of App-V called SoftGrid, was born out of another company called SoftwareWow. SoftwareWow focused on Application Streaming for delivery of the applications, but did not virtualize the applications. I joined SoftwareWow in 1999 due to my background as an expert in developing network protocols.
When we made the change to Softricity to build SoftGrid, streaming remained as one of the core properties of the product value. We led discussions with customers based on three tenants: Centralized Delivery, Streaming, and Virtualization:
- Back then, most software was manually installed by an IT Admin. We didn’t have SCCM or use other Electronic Delivery Systems, with the exception of some home-grown scripting. Install once and deliver globally was a great value proposition to the enterprise.
- Because of our streaming background, delivery via streaming was important to us. And we found that customers reacted extremely well to the streaming. If they remembered nothing else of what the sales person told them, they remembered the demo. The user doesn’t have the app, a shortcut appears, they launch the app and just the portions needed stream over and the app launches quickly. Most competitors also implemented and featured streaming, with the exception of ThinStall (later known as ThinApp), which focused solely on the virtualization feature.
- Solving application conflict, especially “DLL hell”, and allowing multiple versions of the same application simultaneously.
What is Streaming?
But what is “streaming”? When viewed from the standpoint of the receiver (the virtualization client software), streaming is acting on the contents of the source (the virtual package) before receiving the entire contents. In the case of App-V the entire contents refers to the entire App-V package file.
The concept of dynamic application delivery is more appealing when the dynamic delivery is fast. While we can always suggest faster disks, faster networks, and faster processors, streaming is quite appealing as it allows for a more immediate consumption of the application. Of course, in reality we usually aim to get the entire package pre-cached by pre-deploying the package before the user even asks for it.
This streaming is implemented differently in the original implementation (SoftGrid and App-V prior to 5.0) and in 5.0. But in both cases, the streaming is implemented with an understanding that the Windows file system supports the consuming of files based on 4k file boundaries.
Streaming Prior to 5.0
Streaming with SoftGrid, and App-V prior to version 5.0, was implemented based on in two ways.
First of these was the development of a streaming source file format. Internally known as the “Jigsaw format”, the base file format of the SFT package file included a division of internal files based on 4k file blocks, to mimic how Windows pages executable files from the local disk when running applications. This file format, along with the file system drivers implemented at the client, allowed for the client to request individual blocks on demand. For efficiency, the format actually packaged multiple of these blocks into a delivery chunk, and the chunk could be individually compressed for improved storage and delivery. Originally there were 8 blocks (32kb before compression) in a chunk by default, and later 16 block chunks were used.
Second, the Jigsaw format allowed for customization of the layout of chunks within the file to optimize delivery. We focused on optimizing the initial launch of the application, defining a “Feature Block” that would contain only those blocks needed to start the application. This allowed for the client to make a single efficient request for the data, and because this feature block was stored contiguously on the disk, it made reading of the block when stored on rotating media more efficient also.
As a side note, we originally implemented two “feature blocks”, the first (FB1) containing the blocks to start the application, and the second (FB2) which held the remainder of the contents, which normally would be requested individually by the client on demand. But our plans called for implementing additional feature blocks eventually. We believed that we could monitor package use of FB2 at the client in order to define additional feature blocks that contained contents needed for a particular feature (such as the “mail merge” feature in Word). So while never implemented, the idea was that we could have multiple of these feature blocks defined in the file format, with the final block being used as FB2 was currently used.
The package metadata included a listing of file offsets against the overall Sft file. So if the application requested the bytes from the range 0 to 4k of DataFile2, this would be known to the client as part of Chunk N+1, which would be downloaded and decompressed if not present at the client.
This streaming could have been implemented using complete files, which is how Citrix Streaming was implemented.
SoftGrid and App-V before 5.0 also used an external XML file to control the virtual application and streaming process. The OSD was actually a very early attempt at logically defining a software package for publishing purposes. Originally proposed by Microsoft and Marimba in the mid-1990s, the proposal to the IETF went nowhere and was then abandoned until we picked it up and extended it for application virtualization when we built SoftGrid. As we will see in App-V 5, the idea of a common file format to define a software package is of interest today by many technologies.
Streaming in 5.0
App-V 5.0 uses a different format to define the package. See https://blogs.technet.com/b/gladiatormsft/archive/2014/09/20/app-v-5-on-app-v-package-modernization-with-the-opc-open-package-container-or-one-package-container-to-rule-them-all.aspx for a blog post introducing the format used.
This format is rooted in the Open Packaging Conventions (OPC) of ISO 29500-2 (https://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=51459), which is the basis of formats for Microsoft Open Office (https://msdn.microsoft.com/en-us/magazine/cc163372.aspx), AppX, the package format for “Modern” applications (https://msdn.microsoft.com/en-us/library/windows/apps/hh464929(v=VS.85).aspx), and App-V (not yet formally documented). In addition to sharing a base of ISO 29500-2 with these other formats, App-V leverages some of the XML formats used in AppX.
OPC defines a flexible container format to encapsulate a “package” that contains multiple items. For the Open Office format, the container can represent a Word or Excel document, for example. For AppX, the container would represent an application. For App-V, the container represents a package of virtual applications.
OPC allows for use of the Zip format for the overall container. Zip was originally defined by PKWare, but they made the format public in 1989 (https://www.pkware.com/documents/casestudies/APPNOTE.TXT). OPC specifies a subset of the ZIP format for usage, and imposes a number of restrictions on options that specifically may not be used.
The ZIP format consists of a header (located near the end of the file), a central directory, and a number of records. The central directory provides the list of files, and for each file the offsets compressed into which records. Each record is up to 64KB (pre-compressed) of an individual file. In addition to the compressed data, the record contains the full file name, attributes, and extended attributes. Although App-V could have added its own extended attributes as part of the record,
OPC mandates the 64-bit extensions to zip, and that only the “deflate” protocol may be used for the compression. There are also a number of other restrictions, such as allowable file-names, and a prohibition to encrypting files (you could include a file that was externally encrypted, but if you use the ZIP encryption you need to get a license from PKWare).
OPC also defines, but does not require, one specially named folder in the archive (_rels). This folder contains xml files defining relationships. App-V does not make use of this optional part of the OPC.
Content Types
OPC defines some particular files, which generally are optional. One required file is the “[ContentTypes].xml” file. The ContentTypes file defines how every file should be interpreted based on the file extension or filename. This xml file consists of “Default” elements that map each of the file extensions found in the file to a file type and subtype, and “Override” elements that map specific files.
<?xml version=”1.0″ encoding=”UTF-8″?><Types xmlns=”https://schemas.openxmlformats.org/package/2006/content-types”><Default Extension=”dat” ContentType=”appv/vfs-file” /> <Default Extension=”dll” ContentType=”appv/vfs-file” /> <Default Extension=”HxS” ContentType=”appv/vfs-file” /> <Default Extension=”hxc” ContentType=”appv/vfs-file” /> <Default Extension=”hxt” ContentType=”appv/vfs-file” /> <Default Extension=”hxk” ContentType=”appv/vfs-file” /> <Default Extension=”xml” ContentType=”appv/vfs-file” /> <Default Extension=”rll” ContentType=”appv/vfs-file” /> <Default Extension=”XLL” ContentType=”appv/vfs-file” /> <Default Extension=”XLAM” ContentType=”appv/vfs-file” /> <Default Extension=”xltx” ContentType=”appv/vfs-file” /> <Default Extension=”IDX_DLL” ContentType=”appv/vfs-file” /> <Default Extension=”XLS” ContentType=”appv/vfs-file” /> <Default Extension=”XLSX” ContentType=”appv/vfs-file” /> <Default Extension=”CHM” ContentType=”appv/vfs-file” /> <Default Extension=”DOC” ContentType=”appv/vfs-file” /> <Default Extension=”txt” ContentType=”appv/vfs-file” /> <Default Extension=”xsn” ContentType=”appv/vfs-file” /> <Default Extension=”EXE” ContentType=”appv/vfs-file” /> <Default Extension=”GRA” ContentType=”appv/vfs-file” /> <Default Extension=”FLT” ContentType=”appv/vfs-file” /> <Default Extension=”EPS” ContentType=”appv/vfs-file” /> <Default Extension=”GIF” ContentType=”appv/vfs-file” /> <Default Extension=”JPG” ContentType=”appv/vfs-file” /> <Default Extension=”PNG” ContentType=”appv/vfs-file” /> <Default Extension=”WPG” ContentType=”appv/vfs-file” /> <Default Extension=”ADM” ContentType=”appv/vfs-file” /> <Default Extension=”odc” ContentType=”appv/vfs-file” /> <Default Extension=”INI” ContentType=”appv/vfs-file” /> <Default Extension=”ICO” ContentType=”appv/vfs-file” /> <Default Extension=”TTF” ContentType=”appv/vfs-file” /> <Default Extension=”CNT” ContentType=”appv/vfs-file” /> <Default Extension=”HLP” ContentType=”appv/vfs-file” /> <Default Extension=”manifest” ContentType=”appv/vfs-file” /> <Default Extension=”HTM” ContentType=”appv/vfs-file” /> <Default Extension=”PPT” ContentType=”appv/vfs-file” /> <Default Extension=”XLA” ContentType=”appv/vfs-file” /> <Default Extension=”CNV” ContentType=”appv/vfs-file” /> <Default Extension=”DIC” ContentType=”appv/vfs-file” /> <Default Extension=”MSG” ContentType=”appv/vfs-file” /> <Default Extension=”trx_dll” ContentType=”appv/vfs-file” /> <Default Extension=”msi” ContentType=”appv/vfs-file” /> <Default Extension=”ONE” ContentType=”appv/vfs-file” /> <Default Extension=”onepkg” ContentType=”appv/vfs-file” /> <Default Extension=”H” ContentType=”appv/vfs-file” /> <Default Extension=”ECF” ContentType=”appv/vfs-file” /> <Default Extension=”FAE” ContentType=”appv/vfs-file” /> <Default Extension=”CFG” ContentType=”appv/vfs-file” /> <Default Extension=”HOL” ContentType=”appv/vfs-file” /> <Default Extension=”SAM” ContentType=”appv/vfs-file” /> <Default Extension=”OFT” ContentType=”appv/vfs-file” /> <Default Extension=”POTX” ContentType=”appv/vfs-file” /> <Default Extension=”ACL” ContentType=”appv/vfs-file” /> <Default Extension=”LNG” ContentType=”appv/vfs-file” /> <Default Extension=”LEX” ContentType=”appv/vfs-file” /> <Default Extension=”dub” ContentType=”appv/vfs-file” /> <Default Extension=”SCM” ContentType=”appv/vfs-file” /> <Default Extension=”CSS” ContentType=”appv/vfs-file” /> <Default Extension=”OPG” ContentType=”appv/vfs-file” /> <Default Extension=”dotx” ContentType=”appv/vfs-file” /> <Default Extension=”ITS” ContentType=”appv/vfs-file” /> <Default Extension=”xsl” ContentType=”appv/vfs-file” /> <Default Extension=”tlb” ContentType=”appv/vfs-file” /> <Default Extension=”rdlc” ContentType=”appv/vfs-file” /> <Default Extension=”xap” ContentType=”appv/vfs-file” /> <Default Extension=”config” ContentType=”appv/vfs-file” /> <Default Extension=”xrm-ms” ContentType=”appv/vfs-file” /> <Default Extension=”mui” ContentType=”appv/vfs-file” /> <Default Extension=”TTC” ContentType=”appv/vfs-file” /> <Default Extension=”OCX” ContentType=”appv/vfs-file” /> <Default Extension=”ORP” ContentType=”appv/vfs-file” /> <Default Extension=”PSP” ContentType=”appv/vfs-file” /> <Default Extension=”chr” ContentType=”appv/vfs-file” /> <Default Extension=”SHP” ContentType=”appv/vfs-file” /> <Default Extension=”INF” ContentType=”appv/vfs-file” /> <Default Extension=”ELM” ContentType=”appv/vfs-file” /> <Default Extension=”OLB” ContentType=”appv/vfs-file” /> <Default Extension=”man” ContentType=”appv/vfs-file” /> <Default Extension=”CAB” ContentType=”appv/vfs-file” /> <Default Extension=”eftx” ContentType=”appv/vfs-file” /> <Default Extension=”thmx” ContentType=”appv/vfs-file” /> <Default Extension=”ODF” ContentType=”appv/vfs-file” /> <Default Extension=”pri” ContentType=”appv/vfs-file” /> <Default Extension=”propdesc” ContentType=”appv/vfs-file” /> <Default Extension=”gpd” ContentType=”appv/vfs-file” /> <Default Extension=”cat” ContentType=”appv/vfs-file” /> <Default Extension=”MOF” ContentType=”appv/vfs-file” /> <Default Extension=”WAV” ContentType=”appv/vfs-file” /> <Default Extension=”kic” ContentType=”appv/vfs-file” /> <Default Extension=”CPL” ContentType=”appv/vfs-file” /> <Default Extension=”msp” ContentType=”appv/vfs-file” /> <Default Extension=”WMF” ContentType=”appv/vfs-file” /> <Default Extension=”MID” ContentType=”appv/vfs-file” /> <Default Extension=”BMP” ContentType=”appv/vfs-file” /> <Default Extension=”BDR” ContentType=”appv/vfs-file” /> <Default Extension=”ICM” ContentType=”appv/vfs-file” /> <Default Extension=”PUB” ContentType=”appv/vfs-file” /> <Default Extension=”POC” ContentType=”appv/vfs-file” /> <Default Extension=”DPV” ContentType=”appv/vfs-file” /> <Override PartName=”/AppxManifest.xml” ContentType=”application/vnd.ms-appx.manifest+xml” /> <Override PartName=”/AppxBlockMap.xml” ContentType=”application/vnd.ms-appx.blockmap+xml” /> </Types> |
Although I am unsure if the [ContentTypes].xml file is actually used by the App-V client, the sequencer does product such a file as part of the package, which would be necessary to claim compliance with the format. As shown in the example (from the virtual Microsoft Office 2013 package), there are only two “override” elements:
- AppXManifest mapped to “application/vnd.ms-appx.manifest+xml”.
- AppXBlockMap mapped to “application/vnd.ms-appx.blockmap+xml”.
All of the remaining file extensions contained in the package are mapped to a general “appv/vfs-file” file type and subtype. In this case, vfs means that it is a file in the package and does not specify PVAD versus VFS. This default types includes the xml extension which covers the remaining xml metadata files located above the “root” folder.
AppXBlockMap
The AppXBlockMap file contains information for each file in the zip archive which appears to be more about file verification. Each file element in this xml has the uncompressed file size, and logical file header size, plus a sub-elements for each of the zip records. The sub-element indicates the uncompressed size of the block, and a calculated hash for the block. Given that this information is largely discoverable via the central directory with the exception of the calculated hash, it seems reasonable to assume that this is used as an extra level of verification used in AppX and borrowed by App-V.
AppXManifest
The AppXManifest is an extended version of what AppX uses to define applications. App-V adds to the syntax defined by AppX to add virtualization specific information. A subset of the AppXManifest file is produced external to the package by the sequencer in the form of the DeploymentConfig.xml and UserConfig.xml files. It is part of the metadata required by the client, but not part of the streaming format.
StreamMap
The StreamMap.XML file is what defines the feature blocks of App-V 5. In App-V 5, there are three feature blocks, the first two of which are roughly equivalent to FB1 of the old system.
- Primary Block: This block includes all file (parts) of the archive that are necessary to add the package to the client during “add-appvclientpackage”. Certain required files (those above the “root” folder) are assumed and not listed but are automatically brought in by the client.
- Publishing Block: This block includes file parts needed for publishing. This will include portions of each application exe (even if not launched, the client needs the file header brought down), the icon files (for the shortcuts to look right), and any file parts launched during streaming configuration.
The files listed may contain sub-elements listing the blocks involved (the entire file is needed when no block elements are recorded). These block elements consist of a starting block number, and the number of blocks needed. The block number refers to which compressed block of the file (1 through N).
The remaining files and file parts are part of the third (unnamed) feature block and are streamed on demand.
If during streaming configuration in the sequencer, you select the checkbox to “Force application(s) to be fully downloaded before launching” then the StreamMap will consists of only a PrimaryBlock with an indication for full loading.
FileSystemMetaData
According to the Zip format, the central directory may contain records for both folders and files. OPC, and App-V, only record files in the central directory. The file names provide the relative path information, allowing the client to be able to extrapolate the folder objects needed in the Cache.
Unless there is a folder in your App-V package that contains no files. While I am unsure that OPC prohibits the inclusion of directory objects in the zip central directory (the specification is a little fuzzy about that), it is not something that the Open Office Format would expect. So the designers of the App-V file format chose to create a special XML file to hold this and other special file-system data.
The FileSystemMetaData file contains two types of XML elements. The first lists the path for all “empty” folders. This is why you don’t see any empty folders if you just open the AppV file using a standard zip utility (which is unaware of the special purpose of the FileSystemMetaData file).
The second element type is for defining “opaque” folders. These are folders (whether empty or not) that are marked OverrideLocal in the virtual file-system editor. This setting could have been added as a special attribute to a folder object in the zip archive central directory, if folders had been added.
A potentially missing element in this file would be folder “deletion markers”. Just as registry keys and registry items can be deleted while sequencing and recorded, potentially folders and files deleted while sequencing could have been recorded. App-V 4.* had deletion markers for both the registry and the file systems, while App-V 5 supports only registry system deletion markers. I am unsure why this was skipped, but honestly I can’t (currently) think of an application where I require that feature.
Summary
Streaming is alive and well in App-V 5, but do you really care? I say that streaming is important, but configuration of the streaming in a package is often irrelevant.
Most App-V implementations do not require streaming configuration. It only affects the first time use of the application package by the user. The addition of “background streaming” in recent years makes real-time “fault streaming” a rare event.
For most App-V environments, you either want to configuring the streaming by launching nothing (because you are using the App-V Server for publishing in a semi-persistent environment like XenApp), or use the checkbox (because you are using SCCM with BITS, aka “download and run” for delivery).
Streaming is important in non-persistent VDI, although you typically enable Shared Content Store Mode, so streaming configuration is irrelevant (everything is fault-streamed without caching).
References
Other Authorities
https://blogs.technet.com/b/gladiatormsft/archive/2014/09/20/app-v-5-on-app-v-package-modernization-with-the-opc-open-package-container-or-one-package-container-to-rule-them-all.aspx………………………… 3
https://msdn.microsoft.com/en-us/library/windows/apps/hh464929(v=VS.85).aspx……………………… 3
https://msdn.microsoft.com/en-us/magazine/cc163372.aspx…………………………………………………….. 3
https://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=51459………… 3
https://www.pkware.com/documents/casestudies/APPNOTE.TXT……………………………………………… 3