One great benefit of ThinApp’s bubble-to-bubble communication feature, called AppLink, is that you can have application dependencies assigned either static or dynamic. This will allow you some great flexibility but can just as easily make your design quite complex. As always, just because we support a feature or a usage of a feature doesn’t necessarily mean you should use it. In this blog post will I tell you about some of the functionalities of AppLink and then leave it up to you to decide how you’ll implement it…
First some AppLink basics
AppLink works on a Parent – Child type of relationship and will allow you to separate dependencies of an application into separate ThinApp packages. You link packages needing these dependencies together when a need or desire arises to separate these dependencies such as a subcomponent needing frequent updates or the same subcomponent needed by multiple applications. ThinApp supports up to 250 AppLinks. This is probably far more than you should ever use as keeping track of all files and registry keys will be more or less impossible at that scale…not to mention the Isolation Modes. 🙂
When two packages are AppLinked, ThinApp will first load the virtual environment of your main package. Upon loading of the ThinApp runtime, it will scan for any defined AppLink packages and merge the virtual environments of those packages into the current running virtual environment. This will happen every time you start the main package so any updates to your AppLinked packages will be applied during next start. Once all virtual environments of each child ThinApp package have been successfully merged together the application defined will execute. This merge of environments is not a load of everything into the client’s memory. It only loads what is needed in the order defined by listed child packages in order to present the new active virtual environment to the application.
Again, linking ThinApp packages is done in Parent – Child type of relationship where the "parent" ThinApp is modified to look for the "child" ThinApp package. It is the "child" package’s data container we are looking for. This is important since the name of a data container can be either .exe or.dat. So you need to make sure you address the correct file extension of the "child" ThinApp package data container.
One other important thing is, since the "child" ThinApp package can be either a few extra files and registry setting or a whole application which is used separately, keep in mind you may have settings stored in the "child" ThinApp package’s Sandbox and the "parent" ThinApp package will not see these settings as ThinApp does not load the "parent" and "child" ThinApp packages into separate virtual environments – rather, the "parent" ThinApp package imports everything it needs from the "child" AppLink'ed ThinApp package into the "parent" ThinApp package's virtual environment – using the "parent" ThinApp package's sandbox to store all of these settings and configurations. So keep in mind, when you do AppLinking there can be only one Sandbox in use and that is the Sandbox of the "parent" ThinApp package. ThinApp will not look for any settings stored in the "child" ThinApp package’s Sandbox.
Flavors of AppLink
AppLink comes in two flavors, OptionalAppLinks or RequiredAppLinks. OptionalAppLinks will add whatever the package finds but will happily execute if it doesn’t find any. RequiredAppLinks demands all "child" ThinApp packages defined be present and accessible in order for the "parent" ThinApp package to launch. Otherwise, the "parent" ThinApp package will deny the user execution of it.
If you AppLink a "parent" package with "child" package and both packages share the same file or registry entry in the same path, there will be a conflict. So how does ThinApp handle this and which version should be made available to the resulting active virtual environment? When it comes to conflict resolution of files and registry keys the last loaded package wins. The first package loaded is always the "parent" package (the one started by the user), so all "child" AppLinked packages will win any file and registry key conflicts between the parent and child. If you add multiple AppLinks, ThinApp will, by default, use an alphabetic load order when wild cards are specified, or you can also specify a hardcoded load order in the package.ini file.
Example fixed load order:
OptionalAppLinks=c:\plugins\Package 1.exe;c:\plugins\Package 3.exe (package 3 loads last and therefore will win any conflicts)
But very important to keep in mind is the conflict handling of Isolation Modes. Here AppLink will use a different logic. When it comes to Isolation Mode conflicts the most restrictive will win. This happens no matter where in the load order the conflict happens.
Isolation Mode conflict handling:
WriteCopy vs. Merged WriteCopy wins
WriteCopy vs. Full Full will win.
The true dynamic nature of AppLink
Using OptionalAppLinks is, of course, dynamic in nature. You can either have or not have an AppLink or multiple AppLinks loaded. And wildcards can make ThinApp AppLink even more dynamic.
The above example is one you may all recognize from the example found in your default package.ini file. Not much to say about it. It will load any packages (one or multiple) it can find as long as they have the extension .exe. Make sure to change to .dat if that is the name of your data container.
This one might be new to some of you. Yes, you can use wildcard in the file name. This is useful if you like to deploy your, for example, Java ThinApp packages into one specific folder and you include the version number within the file name.
PathToAppLinks\Java JRE 1.3.exe is the old AppLink. Deleting this package and copy the new updated package to your machine, PathToAppLinks\Java JRE 1.6.17.exe . The AppLinking would still be active.
Here comes a new one. Using wildcards in the path was introduced in version 4.6 of ThinApp. It will not work recursively. Every child folder must be represented by a wildcard. One benefit with this approach is that you can now turn to other means for managing AppLinks. You could use NTFS permissions for example. If the end user cannot read the content of a folder, AppLinking to packages within that folder will not occur.
OptionalAppLinks=c:\AppLinks\*\*\*.exe will AppLink packages located in c:\AppLinks\Folder 1\Child Folder1 but not to any packages located in c:\AppLinks\Folder 1.
OptionalAppLinks=c:\AppLinks\*\*.exe will AppLink packages located in c:\AppLinks\Folder 1 but not to any located in c:\AppLinks\Folder 1\Child Folder1.
ThinApp supports nested AppLinks. Meaning, one package (a "parent") can load another package (a "child") which, in turn, has it's own AppLink settings to another package (a "child" of the "child"). This results in all packages being loaded into one big virtual environment or bubble.
Always activating OptionalAppLinks?
You can configure all your "parent" packages to always search a specific location for AppLinked ("child") packages (e.g. OptionalAppLinks=plugins\*.exe) and then, if you later want to AppLink something you can simply use an empty "parent" package with AppLink settings pointing to your real ("child") AppLink package. Only thing to keep in mind is, the empty parent package used to address the child package should be set to only use Merged as the defined Isolation Modes throughout and be as empty as possible. This is to ensure you do not create conflicts between the empty "parent" package and the AppLinked "child" package – remember, most restrictive isolation wins in an AppLink of ThinApp packages. One way to do this is to simply delete all Folder Macros to make sure no virtual file system exist as well as empty the registry hive text files – then set DefaultFolderIsolation and DefaultRegistryIsolation to MERGED within the PACKAGE.INI file. An Isolation Mode of Merged is important since it will essentially remove any Isolation Mode conflicts between the empty "parent" package and AppLinked "child" package.
This can be quite powerful since you do not have to know upfront where you will store your AppLinked packages.
Best practices when it comes to application dependencies
First let me just say best practices are in the eye of the beholder (ThinApp Mantra #6). This is often true but with IT in general, however with ThinApp perhaps even more so as there are usually many different ways of a specific end result. With ThinApp, our developers strive to make it as flexible as possible because this ensures ThinApp can support as many different types of environments and deployment designs as possible.
I tend to provide the following example implementation when it comes to dependencies and packages.
Let’s use Java JRE as our example dependency. Keep in mind that we are able to isolate Java so you can run multiple different Java JREs on the same machine at the same time.
1. On your local clients you have the latest and greatest Java JRE locally installed. This version of Java will be used by most of your ThinApp packages and works most of the time by default when you have packaged an application.
2. For the single really old legacy application demanding Java JRE 1.3x will we package Java together with the application, creating one completely self contained package. This Java will be isolated from the locally installed so the application will happily run on your clients.
3. And last, for the ten apps that demand Java JRE 1.5x will we package Java JRE separate and use AppLink to link the ten ("parent") apps to the ("child") Java version 1.5x package.
Again, this is just one way of addressing dependencies but I kind of like this approach.
Using AppLink in order to update a package
Though designed to handle dependencies nothing stops you from using AppLink in order to update a deployed package. The update can be a simple configuration file update. Since the AppLinked "child" package will win any file / reg.key conflicts is this a great use case.
Your "parent" package has this configuration file: C:\Program Files\ApplicationName\MyConfiguration.ini
To update the application’s configuration simply create an empty project with the updated file located in the same path (C:\Program Files\ApplicationName\MyConfiguration.ini) and AppLink it to the "parent" package.
Other more complex updates can be deployed with the help of AppLink as well but the dynamics often used with AppLink makes it not so suited for security and service packs updates. It will work but if you use OptionalAppLinks are you always running the risk that the "child" package is not present and you will be running unpatched.
Updating an AppLink'ed package
Not many of you may know that AppLink supports the great feature called in-place update. As a bit of a history lesson, this feature has been called many different names like side-by-side (SxS) updates or integer updates. This feature simply provides a means to deploy an updated version of a ThinApp package to a client or network share even though the original ThinApp package is locked / in use. Simply take the newer version of the ThinApp package and change the extension from .exe or .dat to .1, .2 or whatever number that you like, keeping in mind the highest will win. Next time the package is launched the newer version will automatically be used instead of the original one.
A short video about in-place update can be viewed here: http://blogs.vmware.com/thinapp/2009/06/thinapp-sidebyside-application-updating.html
As you can imagine, combining the in-place updates feature of ThinApp with the AppLink feature can be very powerful and provide some high levels of flexibility when deploying, updating, and administering applications in your network environment.
Thanks Dean Flaming for helping me get rid of most of the Swenglish in this post..