Click here to Skip to main content
15,886,026 members
Articles / Programming Languages / C#
Article

A .Net Auto-Updating Project Template

Rate me:
Please Sign up or sign in to vote.
4.15/5 (16 votes)
4 Mar 200410 min read 61K   1.6K   29   9
A basic template to show how to create auto-updating apps using the .Net framework.

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”.
 

Image 1

 

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]
static void 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:

Sample screenshot
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:

[STAThread]
static void Main()
{
 try
 {
  string codeBase = "<A href="http://localhost/AutoUpdater/">http://localhost/AutoUpdater/</A>";
  Assembly uiAssembly = Assembly.LoadFrom(codeBase + 
                                     "AutoUpdaterTemplate.UI.Win.dll");
 }
 catch(Exception err)
 {
  MessageBox.Show(err.Message);
 }
}

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:

Type type = uiAssembly.GetType("AutoUpdaterTemplate.UI.Win.MainForm", true, false);

Finally, we’ll plug that form back into our application with this:

Application.Run((Form)Activator.CreateInstance(type));

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:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <appSettings>
  <add key="codeBase" value="http://localhost/AutoUpdater/" />
 </appSettings>
</configuration>

Now we can change that variable initialization line in our main method and we wind up with this:

[STAThread]
static void Main()
{
 try
 {
  string codeBase = 
                       ConfigurationSettings.AppSettings["codeBase"].ToString();
 
  Assembly uiAssembly = Assembly.LoadFrom(codeBase + 
                             "AutoUpdaterTemplate.UI.Win.dll");

  Type type = uiAssembly.GetType("AutoUpdaterTemplate.UI.Win.MainForm", 
                              true, false);

  Application.Run((Form)Activator.CreateInstance(type));
 }
 catch(Exception err)
 {
  MessageBox.Show(err.Message);
 }
}

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.

Good Luck.

Travis Merkel
v-trmerk@microsoft.com

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.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Currently doing contract work in good old Redmond, WA. Working for the best company in the world. That's right, I'm a microserf.

Current interests include smart-client development and Longhorn (yes, it is as cool as it looks).

Comments and Discussions

 
Generalthis kind of autoupdate is not the best way to go Pin
jocool255011-Mar-06 11:34
jocool255011-Mar-06 11:34 
GeneralReferenced other compontens on the Form Pin
Mikael Svenson22-Apr-04 21:04
Mikael Svenson22-Apr-04 21:04 
QuestionWhat about option 3? Pin
Julien Couvreur10-Mar-04 12:56
Julien Couvreur10-Mar-04 12:56 
AnswerRe: What about option 3? Pin
TravisMerkel10-Mar-04 14:19
TravisMerkel10-Mar-04 14:19 
GeneralDownload links Pin
hammackj5-Mar-04 15:00
hammackj5-Mar-04 15:00 
GeneralRe: Download links Pin
TravisMerkel8-Mar-04 8:58
TravisMerkel8-Mar-04 8:58 
GeneralDude Pin
Jörgen Sigvardsson5-Mar-04 14:16
Jörgen Sigvardsson5-Mar-04 14:16 
GeneralRe: Dude Pin
Anonymous5-Mar-04 17:24
Anonymous5-Mar-04 17:24 
GeneralRe: Dude Pin
TravisMerkel8-Mar-04 8:23
TravisMerkel8-Mar-04 8:23 
Sorry about all the issues. This is my first time submitting to CP and things didn't work out quite how I expected. Working to remedy that right now.

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

"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

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.