volatile memory sucks...
Saturday, April 01, 2006
The ClickOnce support in Visual Studio 2005 is nice and easy but falls-down in number of areas:

  1. The application manifest (i.e. the "stuff" that comprises your app) is determined by walking the project references of your Windows app.  What this means is that if you have deployment artifacts that are non-reference content or late-bound loaded assemblies then the default ClickOnce mechanism in Visual Studio will not pick them up.
  2. Oftentimes the versioning scheme for your assemblies is driven by your build process and ideally you'd want the ClickOnce version number to be in-sync with your assembly version.  The Visual Studio ClickOnce mechanism has a very limited versioning scheme that is completely decoupled from assembly versioning and is inaccessible outside of the IDE.
  3. For enterpirse scenarios, it is very common to have a segmented network dedicated for specific functions (e.g. development, test, production).  In this scenario the Windows app has to be designed such that certain information (e.g. connection strings, web service urls, etc.) are pushed-into environment-specific configuration files.  The deploy process then involves indicating what environment the built bits should be pushed into and then the appropriate configuration files are pulled-in by the deploy process.  In this way the same set of bits may be "promoted" from dev to test and finally to production.  The default Visual Studio ClickOnce mechanism has no notion of nor capability of dealing with environment-specific information.

For the uninitiated there are four ways to create a ClickOnce deploy package:
 
  1. Via the Window app's Publish property page in Visual Studio (easiest but essentially unuseable for apps of even moderate complexity for the reasons listed above).
  2. Via mage.exe (command-line utility).
  3. Via mageui.exe (Windows app).
  4. Via MSBuild (using the GenerateApplicationManifest, GenerateDeploymentManifest, GenerateBootstrapper and SignFile tasks).


Note that despite the chosen method, everything eventually calls the MSBuild tasks. So, for the cleanest solution you should just cut straight to the chase and call the MSBuild tasks, right? Ah, but here's the rub -- you have to determine what your application manifest is and feed this list to the GenerateApplicationManifest task via an ItemGroup. You really don't want to have this fixed list that you have to maintain but rather have the application manifest dynamically generated for you. This is the real value of mage.exe which you can point to a directory and it will build-up the app manifest for you. Where mage is less than useful is generating the deployment manifest but you can just use the MSBuild task to do this instead.
    
This sample demonstrates how to use mage.exe in conjunction with the ClickOnce MSBuild tasks to resolve the deficiencies with the Visual Studio approach.  The sample consists of a simple Windows app which displays a value stored externally in the application's App.config file.  Note that in this sample there are three versions of this file (stored under the Config directory) -- a "development" version, a "qa" (i.e. test) version, and a "production" version.  They are structurally identical, the only varying bits are the values.  There is also a satellite class library that is late-bound instantiated and invoked when a button is pressed on the app.  There is no reference to this assembly from the Windows app.

In my shop we run the deploy scripts seperately from the build scripts but you could easily tack this on to the end of your build process if so desired.  Have fun!

Download Sample

Saturday, April 01, 2006 1:11:29 AM (Pacific Daylight Time, UTC-07:00) | Comments [26] | ClickOnce | Code#
Tracked by:
"ClickOnce, MSBuild and CAB" (Matias Woloski) [Trackback]
"MSBuild + ClickOnce + Mage.exe = Soluciones para el mundo real" (El Blog de Jul... [Trackback]
Search
Archive
Links
Categories
Admin Login
Sign In
Blogroll
Themes
Pick a theme: