Friday, May 18, 2012

ClickOnce Hell

This post is just a comment on my basic impression of ClickOnce, after having lived through developing for it for several years.

If your application is relatively small and simple, ClickOnce is great.  Basically, one (maybe two or three) project in the solution, compile size relatively small (to handle slow connections if necessary).

The problems start to arise when your solution starts to get complex.  Multiple projects, with references in XAML crossing the projects, and it gets a bit tricky.  Stuff that works fine in Visual Studio tends to not work once deployed through ClickOnce, unless you are very careful in your reference definitions.  It only takes one misdefined definition, and the whole thing can break--and the error messages received will likely be too generic to easily find it.

So with a complex application, ClickOnce becomes completely unfeasible.  In my opinion, it's a piece of crap, unless you keep your application small and simple--then it's great.

I use it on my small and simple applications as it offers easy deployment.

But on the one complex application I support, originally it was deployed as ClickOnce, but at some point the ClickOnce deployment broke, probably due to an incorrectly defined reference.  The application worked fine in Visual Studio, or when installed using WiX.  But it would go so far in ClickOnce, then blow up, and I never could figure out what ClickOnce didn't like.

So it was easier to give up on ClickOnce and switch to installing with WiX and use our own home-grown mechanism for updating the application.  That home-grown mechanism had its own set of problems, but at least it was under our control.

As a final note: WiX is great.  Being driven by XML allowed automatic update of the project definition through Team Systems Build.  If  I get around to it, I might post the recipe for this.  Leave a comment if this recipe would be valuable to you (to encourage me to post it sooner).

Assembly Unloading

I needed a simple way of checking version information of an assembly that was not loaded into memory.  On System.Reflection.Assembly, there is the Load method, but unfortunately, now the assembly is in memory with no way of unloading it--eating up precious RAM.

However, .NET offers the AppDomain.  Simply create a new AppDomain and load assemblies into that for reviewing information of the assembly, then unload the domain.

Example:


System.AppDomain newdomain = System.AppDomain.CreateDomain("DataVerification");
Assembly assm = newdomain.Load("MyAssembly.dll");
MessageBox.Show("Assembly version: " + assm.GetName().Version.ToString();
System.AppDomain.Unload(newdomain);