|
|
Microsoft Application Blocks - Application UpdaterNo Touch Deployment | | How do I get started with "No Touch Deployment?" I can wait until the release of VS 2005, or I can use the Microsoft Application Updater Block now!
This article is not meant to be a rehash of the documentation available on-line at Microsoft. Rather, it is a simple summary of getting started in one of several ways with the Updater Application Block.
First, the Updater Application Block is one of several Application Blocks being released by Microsoft. These Application Blocks solve the common problems that developers face from one project to the next. They solve problems in Data Access (I especially like this one), Exception Handling, and No Touch Deployment of your applications. The Application Blocks can be plugged into your .NET applications quickly and easily.
Let me say right off, that the developers of these Application Blocks have done a great job in development of demo files, sample code that both works, and is documented, help file, several optional ways to deploy; and the demos are provide in C# and VB.NET code!
The Application Updater Block employs a "pull down" implementation rather than the traditional "push down" deployment used by Network Administrators. This means that the Application Updater "poll"s the in-house or remote (over the Internet) server to check for newer versions of applications. If a newer version is found, the Application Updater, running on the client computer, automatically downloads the newer version and can stop the old version of the application and restart the newer version.
There are four different sample demos and their associated source code projects:
- Console-based controller
- Windows service controller
- Self-updating application
- Custom sample including custom downloader, validator, and post processor
The most intriguing code and demo, to me, is the Self Updating version of the sample scenarios. There is another choice for in-house deployment; the Windows Service based deploment scheme. This scenario employs a Windows Service that you would deploy to each machine, in the facility, that runs applications that need to be updated. Through the use of the ServerManifest.xml file, you can describe the applications' versions and locations. Through the use of the Service's AppConfig file you can set the time period for the service to poll the server, looking for new application versions to pull down.
Trying the Demo from Microsoft
After you have downloaded the Application Updater Block and samples from the Patterns and Practices link at Microsoft, there are several steps to get started.
First, you must install the Application Updater Block by double-clicking the .MSI file you downloaded. Next, assuming you didn't read the Readme.txt, as I usually don't, you must install the Quick Start Scripts or the demos and sample code will not work! The Quick Start Scripts create virtual directories on the server, install all the updates to those directories, and configure the client applications to search for updates on the local host web server. After installing the Application Updater, you will find menus under Microsoft Application Block Upadater to run the scripts.
You should note that the "DemoFiles" folders need only one version of the compiled DLL's and EXE's to function, so Microsoft arbitrarily chose to use the C# version. Fortunately, I have switched from VB.NET to C# for much of my current development, so I had no trouble following the code. For this reason, the install script compiles only the C# version. The compiled VB.NET versions would work just as well, and if you wish you can modify the scripts to compile them, instead and place them in the DemoFiles folders simply by substituting "VB" for "CS" in the script path arguments.
Trying the Self Updating Application Scenario
If you have an application that is already running in C# (used in this article), you simply need to add a call to the Initialize method, which will be shown below, to your application. This method will create event handlers to catch the notifications from the Application Updater Block as it needs to notify your application of events when a download of a new version is in progress.
Next, you will need to add the code the event handlers for the events that you have hooked up in the Initialize method. One of the (obviously) most important events is the OnUpdaterFilesValidated event. This event fires when the Application Updater has completed the download of the new version of your application and has Validated (see the help file for discussion on building and using Validation) the new version. I have included the sample code for the Validated event in this article also. Once the Validation of the files has completed, the event handler prompts the user to see if they want to start the new version. If the user elects to start the new version, the StartNewVersion method is called.
The StartNewVersion method is well documented with comments, but it basically starts the new version of the application and shuts itself down.
Starting a New Version of a Currently Executing Application
Starting a new version of an application that is currently executing is a tricky process, but it is not done with "smoke and mirrors." Instead, a "shim" or "starter" or "loader" application is used to start the real application. )The Application Updater supports the running of only one instance of an application at a time. To accomplish this, a program named AppStart.exe, found in the sample code, is started instead of the real application.
The AppStart code uses a system Mutex to verify that no other instance of the real appplication (path) is executing. If no other instance of the application is running, the new application is started. The Application Updater uses a system of directories that places the newer version of an application under, but at the same directory node level, as the previous version. The AppStart application accesses its own AppStart.exe.config file to find where the newest version is located. To set up your own directory structure, you should study the directory structure found under any of the four different Updater scenarios. The Application Updater updates the AppStart.exe.config file with the location of the new version, each time one is downloaded. In this way, the AppStart.exe.config file always points to the newest version of the target application. To execute the target application, we always start AppStart.exe, instead of the target application. This shim (AppStart.exe) is responsible for starting the target application.
There is much more to the Application Updater Block, but probably this is enough for one article. In my next article, I will cover the Manifest Utility, which is used to create the ServerManifest.xml file. This file is located on the server and tells the Updater Application Block, running at the behest of a client application when there is a new version of the application ready for downloading.
By the way, there is an excellent Step By Step of building a Self Updating app at DotNetJunkies, written by Brendon Tompkins. There is also a good article on converting an existing application to use the Updater Application Block by Duncan Mackenzie.
The Initialize Method
This method should be called in the initialization of your application. It starts the Application Updater on a separate background thread. It will poll the server on the interval that you set in the config file.
private void Initialize()
{
// hook ProcessExit for a chance to clean up
// when closed peremptorily
AppDomain.CurrentDomain.ProcessExit +=
new EventHandler(CurrentDomain_ProcessExit);
// hook form close to stop updater too
this.Closed +=new EventHandler(SelfUpdating2_Closed);
// make an Updater for use in-process with us
// this is the Microsoft App Block component
_updater = new ApplicationUpdateManager();
// hook (create) Updater events
_updater.DownloadStarted +=
new UpdaterActionEventHandler( OnUpdaterDownloadStarted );
_updater.FilesValidated +=
new UpdaterActionEventHandler( OnUpdaterFilesValidated );
_updater.UpdateAvailable +=
new UpdaterActionEventHandler( OnUpdaterUpdateAvailable );
_updater.DownloadCompleted +=
new UpdaterActionEventHandler(OnUpdaterDownloadCompleted);
// start the updater on a separate thread so
// that our UI remains responsive
_updaterThread =
new Thread( new ThreadStart( _updater.StartUpdater ) );
_updaterThread.Start();
// get version from config, set caption correctly
string version = ConfigurationSettings.AppSettings["version"];
this.Text = this.Text +
String.Format(" **** VERSION {0} **** ", version);
}
|
OnUpdaterFilesValidatedHandler
private void OnUpdaterFilesValidatedHandler( object sender,
UpdaterActionEventArgs e )
{
lblStatus.Text +=
String.Format("FilesValidated successfully for application '{0}' ",
e.ApplicationName) + Environment.NewLine ;
// ask user to use new app
DialogResult dialog = MessageBox.Show(
"Would you like to stop this application and open the new version?",
"Open New Version?", MessageBoxButtons.YesNo );
if( DialogResult.Yes == dialog )
{
StartNewVersion( e.ServerInformation );
}
}
|
StartNewVersion Method
private void StartNewVersion( ServerApplicationInfo server )
{
XmlDocument doc = new XmlDocument();
// load config file to get base dir
doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile );
// get the base dir
string baseDir =
doc.SelectSingleNode("configuration/appUpdater/" +
"UpdaterConfiguration/application/client/baseDir").InnerText;
string newDir = Path.Combine( baseDir, "AppStart.exe" );
ProcessStartInfo process = new ProcessStartInfo( newDir );
process.WorkingDirectory = Path.Combine( newDir ,
server.AvailableVersion );
// launch new version (actually, launch
// AppStart.exe which HAS pointer to new version )
Process.Start( process );
// tell updater to stop
CurrentDomain_ProcessExit( null, null );
// leave this app
Environment.Exit( 0 );
} |
|
|