Introduction

This article assumes a knowledge of .Net programming. All examples will
be in C# using Visual Studio. A local instance of Internet Information
Services will also be required for testing purposes.

One of the coolest technologies (IMHO) that Microsoft has given us with .Net
is easy auto-updating. However, there isn’t much in the way of good
beginning tutorials out there , with the exception of almost anything written on
the topic by Chris Sells (you’re my hero).

My article is going to show you how I go about setting up the framework for
an auto-updating application, and at the end you should have a good starting
point for something you’d like to do. Or at the very least, you’ll
hopefully be more aware of how easily a simple app can be auto-deployed.

Scenarios

There are many different scenarios for auto-updating apps. I’m going to
give you my views and terminology for them.

1. One-click. This is essentially an app that is always run from a
web link. The user clicks the link and needed files are pulled into the
client GAC’s (Global Assembly Cache) temporary download cache as needed.
If the server files aren’t new, they aren’t pulled.

2. The fully connected stub. In this scenario, a small stub
exe is installed on the client machine. The stub does nothing more than
call assemblies that reside on a different computer out in the ether.
Auto-updating is accomplished merely by updating the ether assemblies.

3. The partially connected stub. This requires implementation
of a pull mechanism. The full app is installed on the client
machine. The stub exe then has the responsability of checking for
connectivity, and then pulling any updated assemblies from elsewhere.

4. The fully disconnected stub. Well, I hate to tell you, but
you’re not getting any auto-updating here. You have nowhere to pull
updates from. No, I can’t help you. I’m sorry.

This obviously is not an all encompassing list. There are definitely
other situations and certainly other ways to approach them. I’m just
listing those that I’ve found most common and how I deal with them.

Starting Out

For this article I’m going to deal with situation number 2. It’s not
the easiest to implement, as you’ll see, but it is still fairly simple and it
will give you a taste for more advanced things. So here it goes.

We will start by creating a new Blank Solution within Visual Studio.
We’ll name this solution AutoUpdaterTemplate. Next we’ll add 2 projects to
this solution. The first will be a Windows Application project and will
become our stub exe. The second will be a Class Library project and will
encapsulate our UI. So now I have a solution, AutoUpdaterTemplate, and two
empty projects, AutoUpdaterTemplate.Deployment and
AutoUpdaterTemplate.UI.Win. My project naming conventions are merely to
help me keep things straight in my head. You’re welcome to use whatever
you’re comfortable with. Just remember that you did later on when
something doesn’t work

The first thing we’re going to do is create a very basic UI. Without
that, there’s nothing to deploy. So…we get rid of the Class1 in our UI
project and replace it with a WindowsForm. Feel free to add whatever you’d
like to your form, but for simplicity’s sake I’m going to stick with a label
that reads, “Auto Updater Version 1.0”.

This will be enough to satisfy me for now. On to the fun stuff.

Auto-Deployment #1

For basic auto-deploy functionality, we first need to remove the pesky
generic form that has been added to the deployment project and replace it with
an empty class. You may find use for the form later, but for now we’re
doing basics only. So we now have a class, AutoUpdaterMain, to start
working with.

Obviously we’re going to need a standard static void Main() method here or
the compiler is going to get very angry at us. So we’ll remove the class’s
constructor (not needed) and replace it with the following:

[STAThread]
staticvoid Main()
{
}

There. We now have an app that does nothing. Not a lot of
fun. Let’s make it show our UI. Add a reference to your UI project
in your deployment project. Open your main class, make sure you have a
using System.Windows.Forms reference, and add the following code to your main
function (or something similar based on your project and form name):

AutoUpdaterTemplate.UI.Win.MainForm form = new AutoUpdaterTemplate.UI.Win.MainForm();
Application.Run(form);

Congratulations. You now have a running app. Try it out.
Not only that, but you’ve now written all the code you need for auto-updating
scenario number 1. Don’t believe me? I’ll show you. But first,
one minor change. Open the AssemblyInfo.cs file located in your UI
project. Change this line:

[assembly: AssemblyVersion("1.0.*")]

to this:

[assembly: AssemblyVersion("1.0.0.0")]

You’ll thank me later.

Now create a directory somewhere on your computer and copy the deployment exe
and the UI dll from their respective debug folders into it. Next, create a
virtual directory, called AutoUpdater, from within IIS and aim it at this new
directory. Finally, type this into your web browser:http://localhost/AutoUpdater/AutoUpdaterTemplate.Deployment.exe

Viola, your app runs. But is it auto-updating? Sure it is.
Here’s the test. Open your Visual Studio command prompt and type gacutil
/ldl. This will list all of the files in your GAC’s temporary download
cache. See your UI dll? See the version? It should be
1.0.0.0 Ok, now change something about your UI’s form. I’ll set my
label to this:

Now
change that AssemblyVersion to look like this:

[assembly: AssemblyVersion("1.0.0.1")]

recompile, copy the new dll into your IIS
directory, and run it in your browser again. You’ll see that whatever you
changed showed up. Not only that, but try the gacutil /ldl command
again. Now two versions of the UI dll are listed. That’s right, the
CLR determined that the version in your cache was old and downloaded the new
one. True .Net auto-deployment.

Auto-Deployment #2

So far, we would have to require that a user
always follow a link to our app. While this is fine for many applications,
we’d like to make it as simple as running any other app on our computer.
No browser required. So we’ll press on.

Ideally we’d like this to be as lightweight
as possible, the best-case is having just a stub exe on the machine, and
possibly it’s related app.config file. However, this means the UI dll
won’t be local on the user’s machine. Goodbye reference. We’ll
remove that from our deployment project now. However, now that we don’t
have a reference to the dll, the code in our main method is broken. We
can’t create an instance of our main UI form in the same way. What’s the
answer? Reflection. As I shall show you now.

This article is not intended to teach you
reflection. It’s much too broad a topic and far outside my current
scope. As related to the current problem, it will be enough for you to
know that reflection is going to allow us to create objects from within
assemblies that we don’t have direct references to.

The first issue we need to tackle is that of
how our exe knows where to look for our UI dll. Normally the CLR would use
the CodeBase property of our exe. This is a reference to the place that
the exe is located. However, this is no good in our case. We need a
way to tell the CLR where to look. Or, better yet, we’ll get the dll
ourselves. This will involve using the Assembly class, which will force us
to add using System.Reflection to our list of using statements. We’ll now
start to rebuild our main method in this new manner. We find we can load
the assembly ourselves using the Assembly class’s wonderful LoadFrom
method. Here’s what we get:

I’ve chosen to abstract out the codeBase for
reasons you’ll see in a minute. Now that we have an instance of our UI dll
we’ll need a little reflection to pull out our form. This line should do
the trick:

And that’s it. You now have a fully
functioning stub exe. The problem? Remember the codeBase
variable? Yep, terrible idea to hard code that. We’re going to look
to the System.Configuration namespace to fix this. Go ahead and add that
using reference now.

Making It Flexible

System.Configuration is going to allow us to
pull dynamic settings from an App.config file. And so, we’re going to need
one of those. Let’s add one to our deployment project. In our new
App.config file we’re going to need an appSettings element as well as a codeBase
element within that. When all is said and done, our App.config file should
look like this:

This is a much better setup because we can
now change the location of our UI dll without having to recompile, we merely
change the config file.

You’ll now be happy to see that if you copy
the deployment exe and it’s related config file to any location on your machine
the app runs as expected.

BUT…is it auto-updating? Well, do the
test yourself. Change your UI. Update the AssemblyVersion.
Copy it to your IIS directory. Now re-run the app from wherever you copied
the exe on your machine. Did it work? Of course it did. Would
I steer you wrong?

Good To Know

FYI: The AssemblyVersion update?
Yep, the CLR uses the version to determine whether or not to pull the new
assembly. You don’t need to update the version every time, but the new
functionality won’t be downloaded unless you do, or unless you run the gacutil
/cdl command. This will clear your GAC’s temporary download cache, forcing
the CLR to download whatever version is available.

Summing Up

That’s it. We’ve now created an
auto-updated app and managed to deploy it in two different scenarios. It’s
just that easy. But is it? Sadly no. All of this has worked,
and will work fine for very simplistic apps, but we must remember that
auto-deployed apps in the previous cases are pulling resource from across the
internet, and thus are subject to the mightly lock down Microsoft has placed on
the InternetZone. To accomplish more advanced features with our apps we’ll
need to start looking into such topics as Code Access Security and Strong
Naming. Alas, those are topics for a more non-introductory article.
And if any of you out there are interest, just let me know, and I shall be happy
to provide.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

I tried your code and it works fine in your test case. If I make a class with a form which has an AxWebBrowser component on it (IE), then I get a target invocation error when trying to execute the DLL.

Any pointers on how to solve this?

I get these interop dll's together with my form.dll:
AxInterop.SHDocVw.dll
Interop.SHDocVw.dll

To accomplish option 3 you have to implement either a push or pull mechanism within your stub exe. In this scenario you can't rely on the dll's you need to be in the GAC's cache, because if it's cleared and you're disconnected then your app is broken.

In option 2, the CLR does version checking for you behind the scenes. So the server will essentially be taking a web request hit for the version of the server-side assembly. The dll on the server will never be downloaded, however, unless it's version is newer than that of the newest version in the GAC's cache. So, for instance, the GAC's cache has UI.dll V1.1 and the server has UI.dll V1.2 then version checking is done and UI.dll is downloaded. But if the server only has UI.dll V1.1 then only the version checking is done.

Travis

---------------------------------

"Many times when you start on a project you think, "Boy, this is never going to be finished," but then it is finished, and you think, "Wow, it wasn't even worth it." - Jack Handey