ClickOnce is a Microsoft technology that enables an end user to install an application from the web without administrative permissions.
That’s great isn’t it?
While ClickOnce may sound great to developers it’s actually a nightmare for Enterprise administrators because they try to prevent users from installing software themselves.
ClickOnce also incorporates an Automatic Updates mechanism which means that users might run different or not tested/approved versions…
It get’s even worse in virtual environments such as VDI and SBC where machines are often non-persistent. Each time the users starts the application they will see a screen similar to the one below while they actually download and install it over and over again:
If the environment is persistent, it’s not guaranteed that the user works on the same machine each day. This means that the application will be installed on every box the user ever logs onto…
How does it work?
In order to understand how we can best treat ClickOnce applications we need to understand how they work since MSDN documentation does not describe this in detail.
ClickOnce does this by installing all required files into
%userprofile%\Local Settings\Apps\2.0\<random folder>\<random app id>.
The <random folder> is composed out of the first 11 characters from the following registry key:
Assemblies and Components
Since ClickOnce is .NET framework technology, it’s likely that such an application comes with .NET assemblies (dll’s).
.NET Assemblies are usually installed and registered in the Global Assembly Cache (GAC) but since that requires administrative permissions they are simply places in the application folder.
Therefore ClickOnce uses Registration-Free activation as described here.
Launching a ClickOnce Application
Finally a shortcut is created in the user part of the Start Menu to launch the application. The shortcut’s target points to an file with the extension "appref-ms". If we open this file with notepad, we can see that it contains the applications URL and the Application’s id:
appref-ms resolves to Application.Reference with the following Shell|Open action in the registry:
rundll32.exe dfshim.dll,ShOpenVerbShortcut %1|%2
The actual process, as visible in TaskManager, that runs a ClickOnce application is dfsvc.exe.
So what to do with ClickOnce?
How you deal with ClickOnce applications is up to you, let’s discuss a few options to handle them.
Option #1: Allow installation
If it’s allright in your environment to have the user install ClickOnce applications it’s a lot friendlier to give them a start menu entry than a hyperlink. Use your favorite UEM or even a loginscript to create a start menu shortcut and point it to:
rundll32.exe dfshim.dll,ShOpenVerbApplication http://ClickOnceUrl.application
Where the url matches what’s inside the appref-ms file and must end with .application
Option #2: Virtualize
My personal preference would be to virtualize a ClickOnce applications using tools like App-V or ThinApp. This enabled us to deploy a ClickOnce application like all other applications and does not rely on the user to install them.
ClickOnce applications are hard to virtualize though. My first attempt was to use the normal capture process. But due to the launch process of ClickOnce application (through the Shell/Explorer.exe) you "step out the bubble" and therefore fail to load assemblies located inside the bubble. In my case the app just crashed but Event ID 59 was in the Event Log:
I troubleshooted this for a while and in the end the solution was so simple that it’s almost too easy!
You can simply pickup the whole application folder including all DLL’s and files, place that in the package and launch the exe from the folder…
To easily determine where the necessary files are you can used the mageui.exe tool from the platform sdk (I have attached this at the end of this post for convenience). Open the application’s manifest (usually named Appname.exe.manifest) and click the Files Tab:
So collect those files, place them in a (virtual) folder of choice and use the exe listed as Entry Point. That’s it!
Option #3: Use a fileshare
Using the same method as option #2, just place the files on a network share and launch the files form there 😉
I have not (yet) found a way to block updates on a ClickOnce application. If you do, please let me know so I can add it to this post!