Returns and Specialization
It seems like it’s the season of returns. I’ve returned from Idaho which is where I was returned the favor of spreading a cold to my wife (my entire family was fairly sick over the holidays and I managed to catch their particular flavor of cold/flu). What makes this particularly bad is that I was just about fully recovered from a fairly nasty flu I picked up around Thanksgiving. So I’ve returned back to the “recovering state” of which I’m getting fairly tired. I’m waiting to return to just being healthy Kris. And on a side note: it’s about time for Tax returns… If you’re not thinking about yours you should be.
Okay so personal details aside, I’d like to talk a bit about specialization.
I’ve gotten some feedback that there are developers who are looking to do a little more with VSTO deployment and want to do specialized installation steps. Inherently VSTO ClickOnce doesn’t exactly provide a whole lot of options for extending the installation process. So I’m going to talk today about an alternative and my particular take on it.
Before I go into any details I’m going to talk about some relevant scenarios to try and put into context what we are achieving.
In the first scenario, we may be developing a custom add-in for say Visio that include special templates and objects. In a very extreme case, let us say we’re going to make a game that uses visio as a platform to create something similar to “The Incredible Machine”. In this scenario we need to integrate some specialized objects into Visio for our building blocks. Our add-in then may consist of a series of Physics properties (and logic for automation) associated with each of our special “game” objects. A professional but similar scenario may be business objects with validity rules and business logic that prevent incorrect placement for something like an organizational chart.
Another interest scenario may be around complex solutions: An example may be a “Code-to-Documentation” customized template. In this scenario the user has an existing library of code files (a source control depot of some sort). Part of the installation may be to create a catalog of files to track for documentation (and possibly create a subsequent dataset for add-in consumption). In this case the user would need to go through some special setup wizards to ensure the add-in is pointed to the correct dataset from which to generate relevant documentation.
A final scenario may be a complex solution consisting of multiple customizations. Inherently ClickOnce doesn’t support this concept of multiple applications. Each ClickOnce application lives in its own space and they are all inherently isolated. This can present some interesting difficulties in managing updating and installation. Later I’ll try to put out some ideas on how this might be approached.
So with those scenarios in mind, let’s switch gears and talk about pre-requisites. When you publish a VSTO application you can create a pre-requisites bootstrapper. Basically this is a setup exe that installs various prerequisites you need for your ClickOnce VSTO customization to work. A standard solution will probably contain the following packages: the VSTO Runtime, the .Net Framework, Windows Installer. What you may not know is that you create these packages fairly easily. A link to how to do it is here: https://msdn2.microsoft.com/en-us/library/ms165429.aspx . That said, it’s a very short logical leap from required pre-requisite to required custom installation step. Personally, I think it’s a very “clean” method for handling all of the non-customization parts of a solution. The final goal is to end up with a situation where your pre-requisites dialog looks something like this:
(https://blogs.msdn.com/photos/krimakey/images/6972962/original.aspx).
With this method, a developer is going to wrap up all of the non-VSTO files and steps into a custom installation package (Windows installer MSI), create a product/package xml authoring and do the appropriate work to make it show up in the VS prerequisites dialog. Once all of these steps are done it should be possible to simply add the custom package and then publish the customization. Since the pre-requisite package can be any installation MSI, it should be possible to do anything that is necessary at installation time. Additionally if MSI is used, an entry is created in the Add-Remove-Programs table. This gives the developer the chance fully and properly un-install their solution and all its parts (albeit any custom uninstall steps have to be developed by the developer and are not handled by ClickOnce).
This method is particularly effective if the number of custom steps needed is small and static in nature (ex: in the visio game scenario the developer would not want to make changes to the custom objects used in the game for every version). However there is no “ClickOnce” to these parts so the developer loses the convenient updating mechanism for anything beyond the code-behind.
Another Idea might be to build an “Installation configuration manager” for the solution. This might be an effective solution for the complex applications consisting of multiple components or “paired” customizations. Let’s consider the following case:
We have 2 add-ins (A and B) both A and B rely on the other existing and running in order to properly function. On option in this case is for the developer to build a third component, the AIM component (Add-in-Manager) to ensure parity is maintained. In this scenario the developer creates 2 custom packages. One installs Add-in B (via a custom install step such as shelling out a vstoinstaller request) and the other one installs the AIM. So running the A bootstrapper will install both the AIM and Add-in B and finally Add-in A.
Once that is done, the “Magic” for updating occurs via the AIM. Basically when each Add-in starts up it will communicate with the AIM. The Add-in indicates to the AIM it’s version. The AIM would then do one of 2 things: Return Status Okay (in which the Add-in runs as normal) or Return Shutdown Request (in which the Add-in would run in a “disabled state”, probably prompting the user that a shutdown is required).
Basically the idea would be:
If the Add-in is too old, it needs to shutdown (at which point a thread of the AIM could force an update).
If the other Add-in has been un-installed, a shutdown needs to occur to allow the AIM to uninstall the “left-over” add-in and itself.
In this way, the Add-in doesn’t execute any functionality until it is certain all of the pieces are up-to-date. This solution would be a lot more difficult though, because the developer would have to implement the AIM part which does all of the work.
With all that in mind, it is possible to do some specialization of the installation, it's just not as ClickOnce in nature as we might initially want.
Thank You for reading,
Kris