I was playing the role of a consultant in a small software house for almost a year. The software house developed large-scale health care software for a corporate health care establishment. The software was architected as a true three-tier model. The business tier (middle tier we can say) was written in J2EE (using couple of fancy frameworks like Spring, Hibernate etc) and was hosted in a Web Logic servlet container. And the client tier was written in C# using Windows Form API. The communication protocol between these two tiers is SOAP Web Service.
The deployment process was a big deal because they needed to distribute the client application into over 350 machines (the client terminals) – although it was an XCopy deployment. Well this is a known and old pain of desktop application deployment. But the software is in a maintenance mode, and naturally, the bugs and new enhancements requested are getting noticed on a regular basis and some developers are working on those.
Essentially another old pain introduced is redistributing the updates among the client terminal machines. We already know that many applications update themselves automatically (for example, messenger applications i.e. yahoo, MSN, skype etc). Therefore, the company was simply looking for such a solution.
Eventually, when they notified me about this, I searched on the internet to see if somebody already did something on it or not. But I did not find any general solution on this (rather the proprietary solutions). Finally, I wrote a quick solution (which I am going to discuss in this article) to make the workaround. I am not saying that my approach is a standard/best (or any other adjective) but it just worked for us.
When I started documenting the workflow of this auto update use-case I found the followings execution points:
|A.||The application (assume the application is running in a process named process A) will have a button with text "Check for updates" and after clicking on it, it will request the server if there are any updates available or not. If there are no updates available then the application will continue from the point G (below mentioned). |
|B.||If any updates are ready, then it will notify user that updates are ready to be downloaded, and request a response for starting the download task. If the response is negative then the application will continue its work from point G (below mentioned).|
|C.||If user agrees to update, then the application will launch another process (let's name it as process B).|
|D.||Process B will kill process A first. And then it will download all the files from the server (using remoting and binary formatters- it is worth using these because we are in an intranet environment).|
|E.||Process B will re-launch process A (which is the main application essentially).|
|F.||Process B will terminate. |
|G.||Process A will continue its task as usual.|
Simple enough I believe.
Now, let's start thinking about the implementations.
Analyze complexity and select technology
I broke down the tasks into several small parts to analyze where the complexity could arise. And I found only the communication portion was challenging compared to the others. I decided to use .NET Remoting because of its promising architecture and performances over intranet scenarios. I need to thank .NET framework that it has the cool XCopy deployment feature- this provides a clean and simple deployment process and leverages from old native installation hassles. Our target environment is a corporate intranet therefore I am going to use a binary formatter along with TCP/IP channel-because, I believe, this is the best solution over an intranet environment, as there is no firewall present. Essentially it can provide a huge performance to an application.
So far so good, now we can start implementing the solution.
Implementing the update distribution server
First of all, we will implement a remote server which will have an updated copy of our application, and all the terminals will ask/communicate to this server for updates, and this server will respond accordingly. If any updates are available, then it will also provide the updated assemblies to the client terminals via binary format. In real scenario, an application is supposed to build as one or more assemblies (essentially DLLs) so that updates can be applied only by replacing some or all assemblies (DLLs) of that application – rather than replacing the entire application. But, in this article I am going to update *all* the executable (EXEs) and the assemblies (DLLs) just for demonstration purposes. Updating only the necessary assemblies will provide more performance improvement.
First of all I am writing a new project –essentially it is a Windows form application that will host the remote server in it. I am going to write a remote interface first which will play the contact role between the client and server.
public interface IUpdateService
string GetCurrentVersion(string fileName);
byte GetFile(string fileName);
As you might already have guessed, this is the interface that our remote server is going to implement. Now we will implement this interface as follows.
public class UpdateService : MarshalByRefObject, IUpdateService
#region IUpdateService Members
public string GetFiles()
ArrayList collection = new ArrayList();
foreach(FileObject fileObject in ConfigInfo.Instance.FileObjects)
return collection.ToArray(typeof(string)) as string;
GetFiles essentially reads the available update files from a predefined configured directory and exposes the name of each file to its consumer.
public string GetCurrentVersion(string fileName)
foreach(FileObject fileObject in ConfigInfo.Instance.FileObjects)
new ArgumentException("Given file is not found into the server.");
GetCurrentVersion replies with the latest version number of a file that is available on the server. We are going to use the .NET assembly version to keep track of version number. For non-assembly files (for example XML, config etc) it will reply with a string like "NA".
public byte GetFile(string fileName)
new ArgumentException("Given file is not found into the server.");
Now, as the method name says,
GetFile simply returns the entire file content in binary format. And the method reads the file content using the following method:
private byte GetBinaryContents(FileObject fileObject)
using(FileStream fileStream =
using(BinaryReader reader = new BinaryReader(fileStream))
block = reader.ReadBytes((int)fileStream.Length);
It is time to expose the service to the outside world. So I am going to host the service into a Windows Form. Here is the code snippet for exposing the service:
private void StartServer()
TcpServerChannel serverChannel = new TcpServerChannel(7444);
Logger.LogMessage("Registering WKO Objects..");
Logger.LogMessage("Registering WKO Objects..completed.");
The AppUpdateServer project is ready now.
Now it is time to modify our main application which will eventually contact the remote server and ask for updates. To demonstrate this, I am going to write a small application named SampleApplication. It is a GUI application and let's say it has a menu called "Check for Updates". Whenever the user clicks on it, the application will start the update process.
One thing we need to keep in mind is that this application needs the remote URL of the remote server in order to communicate with the remote server. So we need to put that into the configuration file of the SampleApplication. Now, I am writing a class here that will contain the update related stuff (just to keep this code separate from the other business code of the application), which will have a method named "
Update" that will do all the work.
So here is the class implementation:
public class UpdateUtil
private string remoteObjectUri = string.Empty;
private IUpdateService remoteService;
private IWin32Window owner;
private string applicationName;
public UpdateUtil(IWin32Window owner,string remoteObjectUri)
remoteService = null;
this.owner = owner;
this.remoteObjectUri = remoteObjectUri;
As you can see, the class needs the remote object
URI and a
win32 owner (the sample application in this case) as a constructor argument.
private bool ConnectRemoteServer()
catch(Exception remoteException )
return remoteService != null;
ConnectRemoteServer simply establishes the connection to the server using the remote URI.
private bool UpdateAvailable()
applicationName = assemblylocation;
Now, this method performs an important task, it asks the server what version is available at the remote side for the SampleApplication.exe; if any update is available that it returns
true to its caller. The
UpdateAvailable method using the following utility method
IsUpdateNecessary to determine if the available version number is an update over the current one or not.
private bool IsUpdateNecessary(string localVersion,string remoteVersion)
long lcVersion = Convert.ToInt64( localVersion.Replace(".",""));
long rmVersion = Convert.ToInt64( remoteVersion.Replace(".",""));
return lcVersion < rmVersion ;
Now this is the only
public method of the class that actually invokes the above defined method to do the
Update kick. This method does some noticeable stuff inside it. I will explain these now. First of all, the method simply checks if any updates are available, if yes then it *does not do* the
Update process itself. It launches another process AppUpdate.exe to do this job. The theory behind this is simple; the
Update process will replace the current exe. But the system will not allow us to replace an exe file when it is in execution. So we have to launch another process.
public void Update()
if( DialogResult.Yes ==
"An update is available. \nWould you like to update now?",
"Sample Application Update",
Process updateProcess = new Process();
+ " "+remoteObjectUri);
Now, AppUpdate.exe is the only thing that we need to implement to complete the task. AppUpdate is essentially another tiny Windows Forms application (I am using Windows Forms because my intent is to display a progress bar Window during the update process) which will perform the actual update task. This process takes two command line arguments. One is the Process ID of the Sample Application. The other is the remote server URL. The purpose of the latter one is simple to us – I believe. I am just explaining the purpose of the former one. The AppUpdate.exe will replace the SampleApplication exe, so it will first kill the process (inside which SampleApplication is running) and then it will update the application exe's and DLLs, finally it will re-launch the SampleApplication.
Let's focus on to the AppUpdate.exe now.
AppUpdate project contains a single Windows Form class where I have written the
Update stuff. Here are the code snippets:
public class AppUpdate : System.Windows.Forms.Form
private string applicationProcessID;
private string remoteObjectUri ;
public AppUpdate(string applicationProcessID,string remoteUrl)
this.applicationProcessID = applicationProcessID;
this.remoteObjectUri = remoteUrl;
The constructor of the class takes two arguments that I just talked about, one is the application process id of SampleApplication and another is the remote server URI.
public void RunUpdateProcess()
Process applicationProcess =
if( applicationProcess == null ) return;
if( !ConnectRemoteServer()) return ;
RunUpdateProcess is the cue method that will do all the tasks. We will invoke this method when the Form gets loaded.
I mean, when the Progress Window will be activated, we will invoke this method. So we can write an event handler for
inside this class and can invoke this method from inside
. This method kills the SampleApplication
process and then invokes another private method
, the implementation of which is given below:
private void UpdateFiles()
foreach( string file
byte array =
string fileName = Path.Combine(targetDir,file);
FileInfo finfo = new FileInfo(fileName);
if( finfo.Exists ) finfo.Delete();
= new FileStream(fileName,
using(BinaryWriter writer =
Process launch = new Process();
Therefore, we can see that this method copies each updated file from the remote server and replaces the existing ole version with those. Now it is time to run this application's Window – which we are going to do inside the
public static void Main(string  args )
if( args.Length > 0 )
Main method receives the process id and remote URI thru the command line arguments and provides these into the
AppUpdate class while instantiating it.
That's all there is to our implementation.
Review and Test
To test out this solution, first of all we will have to launch the server application. In the server machine, there should be a directory that will contain all the updated assemblies along with all XML files and the config file (as needed). And the server application will read all the file version numbers and expose the remote services. Then we will launch the client application (SampleApplication in this case) and click on the menu "Check for Updates". And the
Update process will work.
Again, this is a quick and easy solution that I have written. So there no reason for me to claim it a standard or "something classic". But I believe this can help the desktop application written in .NET and running in an intranet scenario. In recent days, more classic Frameworks like ClickOnce and XBAP are being used in organizations for this kind of solution.