It can often be a challenge to decouple your applications from the operating system they run on, but there are some ways to do it. Here is one solution that Mark Van Noy, who manages the Virtual Desktop Infrastructure at the University of Colorado Boulder, came up with for solving this problem. Mark has contributed previously in my column here on TechGenix with articles on using VMware Horizon to connect to remote computers and on utilizing Turbo.net, FlexApp, and App-V as application virtualization solutions. Let’s now listen in as Mark walks us through his approach to application layering which he explains in detail along with accompanying screenshots and sample PowerShell scripts at the conclusion of his walkthrough.
Layering applications using VHD
Decoupling applications from the operating system has remained an elusive goal for many IT organizations. Several commercial offerings promise to provide application layers, most often using proprietary methods. These layering methods allow individual applications to be added at will to a base operating system, or even in some cases to have the operating itself managed as a layer so that a pool of operating systems do not need to be maintained for multiple use cases. With a little use of containerization technologies, which are admittedly still proprietary, it is possible to utilize the built-in virtual hard disk, VHD, technology in Windows to attach applications to an operating system at run time.
The first thing needed is some method of application containerization. Simply installing anything other than the simplest applications to a VHD will not work because any local writes to the Registry or user profiles will not get picked up by the virtual hard disk. Some examples of technologies that containerize applications include Microsoft’s App-V, VMware’s ThinApp, and Turbo.Net. A special mention should be made of LiquidWare’s FlexApp as that product handles the containerization of applications and the attaching of VHD’s natively as part of their product. Since I used Turbo.Net to prototype this solution, I will use it for all the examples going forward.
Advantages of layering applications
Any application layering technology promises to move applications out of the OS so that fewer gold images need to be managed. Ideally, a single gold image of Windows can be maintained and patched. Version control is much easier with layering as an updated version of the software automatically gets published to users on their next login when the container in the VHD is updated. Layering also allows for deduplication of storage since applications are stored in a VHD once instead of using space on the local physical computer. Most VDI solutions have built-in deduplication strategies that can already be used for virtual computers. Many existing commercial solutions are built with VDI in mind, which ties them to virtual machines. This often creates a situation where different processes need to be in place for managing Virtual Desktop Infrastructure computers and physical desktops. By using application containerization technologies and placing those containers into VHD files, application layering can be applied to any Windows-based computer. Further, the solution allows managing the images to be a simple process of mounting the VHD locally then copying containers to the VHD or deleting them to add, remove, or update software.
How to layer applications with Turbo.net
First up, an empty VHD needs to be created. Click Start, then type “diskmgmt.msc” to bring up Disk Management on a Windows 10 client. In Disk Management, click on Action and select Create VHD. Choose a convenient location for the VHD to live. This can be either a local path or a network share. Make sure to select VHD rather than VHDX for the virtual drive type. As of this writing, the PowerShell cmdlet required to mount a VHDX is only present when Hyper-V is also installed on the system. This is probably why Microsoft’s MSIX App Attach technology for Azure Virtual Desktops requires Hyper-V to be installed, which would normally be a rather strange thing to install on a virtual computer. Once the VHD is created, it needs to be initialized and formatted just like any new physical disk.
Once the VHD is created and formatted, it shows up much like any other disk. Notice that VHDs have a light blue icon instead of the standard gray. A formatted VHD has a drive letter assigned to it by default. A specific mount point could be specified instead, so it is easy to manage. Double-clicking on a VHD file will automatically mount the VHD allowing files to be moved to and from the VHD just like any other disk.
The next step is to copy in the Turbo containers — .svm files in Turbo parlance — to the empty VHD. There is not much to this. Drag and drop, control-c with control-v, robocopy, Get-Item, or right-click, are all fine.
The final step in getting layering working is to ensure the Turbo client is installed and set appropriate scripts to run. Please note that the sample PowerShell scripts listed at the end of this article assume that Turbo was installed for all users. If Turbo is installed for an individual user then the executable path is in the user’s %LOCALAPPDATA%\cmd path rather than Program Files (x86). The VHD mounting script must be run with elevated permissions, which can be handled by running the VHD attachment as a Scheduled Task running as an administrative account — not SYSTEM. Despite requiring administrative permissions for the VHD information gathering, the script to add applications will work correctly when assigned to a user login Group Policy Object. Also, if using Turbo, make sure that the spoonbrew/clean, spoonbrew/base, and xvm SVMs are installed as they are the glue that allows Turbo containers to function. Without them, the application hooks will show in the Start Menu, but the applications will not launch. (The PowerShell scripts depicted in the images below are listed at the end of the article for easy copying and pasting.)
Performance is always a concern with everything we do in IT. We can increase the performance of applications registered at login by using a shared Turbo cache among all users rather than having each user’s cache live on their local computer. To do this, I created another empty VHD and set it to mount to %LOCALAPPDATA%\Cache during initialization instead of getting a drive letter when mounted. This cache VHD is then mounted at startup just like the application VHD, and a login script tells the Turbo client to point to %LOCALAPPDATA%\Cache instead of the default of %PROGRAMDATA%\Turbo\Containers\Repo. Subsequent installs at the login of applications were as much as 50% faster after implementing a shared cache.
Note on Ivanti User Workspace Manager
The original proof of concept for using virtual hard disk layers containing Turbo containers was fully managed by Ivanti’s User Workspace Manager. Specifically, the Environment Manager’s Policy component was used. This solution brought with it ease of configuration with event-driven management, additional granularity regarding when in the login process VHD mounting and scripts should run, and rich tools for managing VHD mounting. Working to remove User Workspace Manager from the process required a fair bit of trial and error to get a solution. For instance, UWM automatically handles the required elevation to mount a VHD so that step can be configured in the user space in UWM instead of running elevated for the entire computer. There are other tools out there that do similar things, such as Liquidware’s ProfileUnity product. We have been using User Workspace Manager since it was called AppSense, so we have a great deal of familiarity with the product, but that by no means suggests User Workspace Manager is a requirement.
Some final thoughts
So should application layering be used? Honestly, with Turbo, probably not. Turbo has its own built-in subscription functionality that does the same basic thing with less work. Subscriptions pull down all the applications from a specified workspace. Assuming the Turbo client is already installed for all users, a simple login script such as “turbo subscribe marketing” (without the quotes) would layer all the applications in the marketing workspace without having to work with VHD files.
Some scenarios where VHD layering continues to make sense are kiosk-style computers where user profiles do not persist between logins, branch offices that have fast storage available and relatively slow connections back to Turbo servers, and organizations that have some form of application containerization that does not have the equivalent subscription functionality of Turbo. A great example of this is App-V. Using App-V containers inside VHD files combined with startup and login scripts essentially provides the functionality of MSIX App Attach without the limitations of only being able to be used in Azure Virtual Desktops and having to install Hyper-V into client computers that otherwise are not going to use Hyper-V. There are certainly more scenarios where this technology could be a boon. Keep in mind that there is always a delay while waiting for Network Attached Storage to mount any VHDs and present the applications.
Sample PowerShell scripts
Execute-TurboSVM.ps1
# Connect to the drive $imagePath = '\\your.fileshare.here\VHD\Turbo-Test-Layer.vhd' $drive = Get-DiskImage -StorageType VHD -ImagePath $imagePath # Determine the mounted drive letter $letter = (($drive | Get-Disk | Get-Partition | Get-Volume).DriveLetter) + ':\' # Enumerate all the SVMs available on the mounted drive $svm = Get-ChildItem -Path $letter # Iterate over each SVM adding appropriate shortcuts foreach ($entry in $svm) { & "C:\Program Files (x86)\Turbo\Cmd\turbo.exe" import svm --name $entry.BaseName $entry.FullName & "C:\Program Files (x86)\Turbo\Cmd\turbo.exe" installi --skip-installed --offline $entry.BaseName }
Mount-VHD.ps1
$imagePath = '\\your.fileshare.here\VHD\Turbo-Test-Layer.vhd' $vhd = Mount-DiskImage -StorageType VHD -Access ReadOnly -ImagePath $imagePath
Set-TurboCache.ps1
$letter = $env:LOCALAPPDATA + '\Cache' # Specific configuration command to set the Turbo config to use the VHD as cache. & "C:\Program Files (x86)\Turbo\Cmd\turbo.exe" config --gci-expiration=0 --gci-interval=0 --image-cache-size=0 --image-path=$letter # Make sure the core VMs are in the cache or else no packages will launch; critical. & "C:\Program Files (x86)\Turbo\Cmd\turbo.exe" pull spoonbrew/clean,spoonbrew/base,/xvm
Featured image: Shutterstock