Application layering with virtual hard disks and PowerShell

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, 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

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


# Connect to the drive
$imagePath = '\\\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


$imagePath = '\\\VHD\Turbo-Test-Layer.vhd' $vhd = Mount-DiskImage -StorageType VHD -Access ReadOnly -ImagePath $imagePath


$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

Mitch Tulloch

Mitch Tulloch is Senior Editor of both WServerNews and FitITproNews and is a widely recognized expert on Windows Server and cloud technologies. He has written more than a thousand articles and has authored or been series editor for over 50 books for Microsoft Press and other publishers. Mitch has also been a twelve-time recipient of the Microsoft Most Valuable Professional (MVP) award in the technical category of Cloud and Datacenter Management. He currently runs an IT content development business in Winnipeg, Canada.

Published by
Mitch Tulloch

Recent Posts

Low-code/no-code: Benefits, differences, drawbacks, and the future

Low-code/no-code provides a modular approach for developers — and even non-developers — to produce apps…

1 day ago

Are you human or robot? How CAPTCHAs know

CAPTCHAs may be an annoying part of web surfing, but they serve a purpose for…

2 days ago

Pixel 6 unveiled: Finally, a smartphone winner for Google

Google hasn’t had a lot of success with its past smartphones, but the Pixel 6…

2 days ago

Cross-account container takeover: All about this little-known cloud threat

Palo Alto Networks uncovered a cross-account container takeover exploit that could threaten users of the…

2 days ago

IgniteTech adds IT management software to enterprise portfolio

Software maker IgniteTech has added 12 products to its enterprise portfolio, including several focused on…

3 days ago

Olympus Global issues warning about potential cyberattack

Medical systems maker Olympus Global, out of an abundance of caution, is warning the public…

3 days ago