When App-V 5 was initially released there was new method introduced for automatically “sucking” any locally installed application into context of virtual package, RunVirtual client registry key. This method was then improved in App-V 5.0 SP3 to support user published packages in addition to global ones. One thing, however, that is difficult with this method is the fact it has to be written to client’s registry and thus is not easily manageable.
In addition, on contrary to what it says in the KB article linked above, usage of the method does not seem to work Connection Groups directly (at least based on the quick testing we did in workshop few weeks ago with 5.1 release and what Aaron also notes in his blog post of using CG with RunVirtual). There’s also the fact that the syntax required by the RunVirtual expects the exact package id + version id of the package (unlike the improved support for packages in CGs that allowed us to use * as version identifier), which means that if you upgrade the package the method stops working.
Fortunately, there seems to be workaround that works well for both of these scenarios: for logically tying the RunVirtual entry to the CG rather than some specific package, as well as making sure that we can upgrade App-V 5 packages without constantly going back to all clients making modifications to the HKLM branch of the registry.
Quick guide on using RunVirtual
Before showing the method for doing RunVirtual more flexibly, let’s quickly look through how to use the RunVirtual registry key.
In the App-V Client’s registry branch HKLM\Software\Microsoft\AppV\Client, there’s several global configuration values inside different subkeys that you can also set through group policies and via PowerShell command Set-AppVClientConfiguration. These control things like if the client can executable package scripts, if Shared Content Store Mode is in use etc.
One of the things that you cannot set through these configuration interfaces is setting up locally present executable(s) that should be pulled into some specific virtual environment, effectively reverse-integrating locally installed application with some virtual content (say, local Office or Internet browser with virtual add-ons).
For that, you need to modify the registry key called RunVirtual which by default is an empty one. The syntax expected by the App-V Client is to have one subkey per per executable you want to integrate into virtual environment (say, “iexplore.exe”) having the executable name as the name of the key.
For the contents of the registry key’s default value, you need to specify the App-V package using format of <package_id>_<package_version_id>, where the values package_id and package_version_id refers to unique GUID values found inside each App-V package identifying exactly that package. This info is shown during various package management commands in PowerShell session (such as Add-AppVClientPackage) or in the Sequencer.
If, for some reason, you have multiple executables in different places with the same name, you can make the reference to one specific executable by that name by not modifying the default value for the key, but rather adding the executable’s full path as named value under that executable’s subkey.
So for instance if we have a package published that has package id of 26c358c1-16b2-4f7f-aca7-66cda92f71ee and version id 846ba25d-a23f-4022-8e0d-e478b537d738, we would add new key into RunVirtual key, having those values as default value’s data:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\AppV\Client\RunVirtual\iexplore.exe]
@=”26c358c1-16b2-4f7f-aca7-66cda92f71ee_846ba25d-a23f-4022-8e0d-e478b537d738″
After setting these in the registry, whenever we launch a process called iexplore.exe, App-V Client will intercept the process launch and see if it can find published package by the specified IDs and if so, actually loads the iexplore.exe process inside the said package’s virtual environment.
All well and good, but…
As we can see from the example above, this is very handy method for pulling those local processes into context of a virtual package that has some content that somehow relates to the local application being launched.
The downside of course is that this information is now practically speaking hard-coded into each client machine’s registry, and therefore is not really manageable through any meaningful way so that future package upgrades to our locally-integrated packages would still work automatically. One upgrade of one of these packages that you may have listed in the registry, and suddenly our reverse integration stops working as the version id is not matching anymore!
The same is also true if you want to re-sequence the same application/plugin for some reason or another and replace the currently-published version, or if you would rather tie your reverse-integration into some Connection Group you have published (as you may have stuff from more than one VE you would like to load into local application, such as multiple plugins).
Having possibility to do wildcards, like * supported in the CG for package version id, would be good to have but unfortunately that is not available for now for RunVirtual. And it would not solve the issue for completely re-sequenced or branched packages, or the need to include Connection Groups as own entities into RunVirtual.
Stub/proxy package to the rescue!
Fortunately there exists a method that can be used to basically act as a proxy for what we would like to do: use a stub package that triggers the actual thing we want to do!
By stub package, what I mean here is the setup wherein you sequence basically an empty package (it does not have to have anything inside or publish out any applications) and use that as the trigger for the RunVirtual. Now, you of course would not want to publish that stub package all by itself, as that would not serve any purpose really, but rather to construct an additional Connection Group that lists the packages you would want to be included in to the locally installed application’s VE plus that stub package.
The way Connection Groups works is by App-V Client is doing the monitoring of if anything out of any individual package is started on a client, and if so, forming the Connection Group by loading that App-V package and all other packages listed inside the CG into same common VE, merging and sharing the virtual resources. Since in this case we interested running local executable and nothing out of any the packages directly, we rather just tell the App-V Client that we would want it to load local executable into that stub package’s VE, resulting associated CG loading indirectly the actual packages as well.
Since the stub package does not contain anything by itself, we have no need to do any upgrades for it (or need to replace it), resulting the fact that its package id and package version id is not changed at any point. Which was the thing we really wanted in the first place, as we hard-coded those IDs into each client’s registry!
So, now as first action we add our new stub package into App-V Client and then modify entries in the RunVirtual key to refer to this new package instead of the actual package or packages we intend to load.
And we must construct the CG (or use existing one if applicable) that refers to this stub package so we can cause these additional packages to load (you might want to list those actual packages as optional if you cannot make sure they are really published, otherwise adding the CG to the client will fail):
<?xml version=”1.0″ encoding=”UTF-16″?>
<appv:AppConnectionGroup xmlns=”http://schemas.microsoft.com/appv/2014/virtualapplicationconnectiongroup” xmlns:appv=”http://schemas.microsoft.com/appv/2014/virtualapplicationconnectiongroup” AppConnectionGroupId=”61BE9B14-D2B4-41CE-A6E3-A1B658DE7000″ VersionId=”E6B6AA57-F2A7-49C9-ADF8-F2B5B3C8A42F” Priority=”0″ DisplayName=”RunVirtual Connection Group”>
<appv:Packages>
<appv:Package PackageId=”26c358c1-16b2-4f7f-aca7-66cda92f71ee” VersionId=”*” IsOptional=”true” />
<appv:Package PackageId=”d14d5b16-7526-42d1-ab95-8f29fe99290e” VersionId=”*” IsOptional=”false” />
</appv:Packages>
</appv:AppConnectionGroup>
And then we publish and enable the Connection Group we created:
Now, if everything works and when launching our local application, we should have all virtual environments from the CG loaded through our stub package that was acting as a trigger.
And indeed, now we have Firefox package loaded (which stands for add-on package for demostrations purpose, in real life you likely would not really want to load it together with IE! :-)) even though we did not have reference to it directly in the RunVirtual key or to the CG itself.
One additional benefit for doing loading of even one individual package loading through CG instead of directly, addition to other benefits listed above of course, is that now settings cached inside the VE will be maintained independent of that package as App-V Client stores all intra-VE cached settings in CG’s context instead of the package itself! This is different how it used to be with DSC in earlier App-V version, wherein the changes for combined VE were cached inside main package VE but since now with Connection Groups there’s no “main” package anymore the changes will be cached against CG.
Wherein this particular upside comes handy is in situations where you would want to re-sequence the same application, completely or to do major version upgrade, and do not want to lose cached user setting.
Hopefully you find this workaround’ish technique to run CG’d packages in indirect way useful, and it goes without saying that you could also have multiple of these stub packages published, each tied to different set of Connection Groups.
03.08.2016 at 12:25
I was struggling with the same thing. I couldn’t update individual packages within the connection group without changing the HKLM key and you can’t change the HKLM key set by GPO during production.
The use of an empty proxy package is a great find, thanks for this!!