Introduction
I had been trying to include updater block in my application. The quick starts that came along with the application block had some real neat examples, but it took quite some time to figure out what files must be placed where, what settings needed to be made and how, to get a sample of my own working. So, I thought I would post the sample implementation that I generated, along with a step by step guide so that others who will be trying this point onwards need not struggle much.
Note: A good tutorial for updater block version 1.0 can be found here.
The example below tries to show the usage for the version 2.0 of the Updater block.
Prerequisites
- The Enterprise library and the Updater application block must be downloaded and installed. The enterprise library can be downloaded from here.
- The updater block can be downloaded from here.
System Requirements
- Supported Operating Systems: Windows XP.
- Windows XP Professional.
- Internet Information Server version 5.0 or later.
- Microsoft .NET FrameWork version 1.1 SDK.
- Microsoft Visual Studio 2003.
- Background Intelligent Transfer Service (BITS) (for the out-of-the-box downloader to function correctly).
Steps
- Create a simple Windows form application .
- Open VS .NET editor and select File -> New Project -> Windows Application.
- Change the name to SampleApplication.
- Change the name of the default form generated to SampleForm.cs
- Add a label on the form
SampleForm
and set its text to �Version 1.0.0.0�
- Add a button to the form and change its text to �Exit�. Add the event handler to exit the application -
Application.Exit();
.
- Add a listbox called
eventList
.
- Open the AssemblyInfo.cs and change the version of the application to 1.0.0.0: [assembly: AssemblyVersion("1.0.0.0")]
- Change the line in
Main ()
body to Application.Run(new SampleForm());
.
- Add app.config to the application: Add -> New Item -> Application Configuration File.
- Build the application.
- Add the updater application block to the application.
- Update the App.Config file using Enterprise library Configuration Tool.
- Open the tool from Start -> All Programs -> Microsoft Patterns and Practices -> Updater Application Block V2 -> Enterprise Library Configuration Tool.
- In the Configuration tool console, select File -> Open Application and browse to the App.Config file, select and click Open.
- A new item �Application� appears under the root �Enterprise Library Configuration�.
- Rightclick Application and select New �> Updater Application Block Configuration.
- Configuration, Cryptography and Updater Application Blocks are added.
- Update the properties of the application block:
ApplicationID
: SampleApplication.
BasePath
: C:\Temp\UpdaterTest\UAB.
ManifestUri
: http://localhost/ApplicationBlockServer/ServerManifest.xml.
Note: The ManifestUri
will point to a URL that has to be created later.
- Rightclick Updater Application Block and select New -> Downloaders.
- Rightclick Downloaders and select New -> BITSDownloader.
- Save.
- Deploy the Client
- Build the SampleApplication project.
- Copy the output of the project from the bin/Debug folder to the folder C:\Temp\UpdaterTest. The files to be copied are:
- All the DLLs including the following:
- Microsoft.ApplicationBlocks.Updater.ActivationProcessors.dll
- Microsoft.ApplicationBlocks.Updater.dll
- Microsoft.ApplicationBlocks.Updater.Downloaders.dll
- The application exe: SampleApplication.exe
- The config file: SampleApplication.exe.config
- Copy the files updaterconfiguration.config and securitycryptographyconfiguration.config present in the root folder of the project to the folder UpdaterTest.
- Change the project to create the server application.
The server application will be a newer version of the application deployed at c:\temp\ UpdaterTest.
- Open the SampleApplication solution in VS.NET editor.
- Open
SampleForm
in designer mode and make noticeable changes on the form. Change the label text to �Version 1.0.0.1� and the form text to �Sample Form New Version�.
- Open AssemblyInfo.cs and change the assembly version to 1.0.0.1: [assembly: AssemblyVersion("1.0.0.1")].
- Build the application.
- Deploy the Server Application.
The new version of the application will be deployed at the server, from where it can be downloaded.
- Create a folder called ApplicationBlockServer under C:\inetpub\wwwroot.
- Open IIS manager (Start -> Run -> Inetmgr).
- In the IIS manager, navigate to Default Web Site.
- Rightclick on Default Web Site and select �New -> Virtual Directory�.
- Create a virtual directory with alias ApplicationBlockServer and the folder pointing to ApplicationBlockServer folder created above.
- Create a new folder called 1.0.0.1 under the folder c:\inetpub\wwwroot\ ApplicationBlockServer.
- Copy the file SampleApplication.exe built in the previous step to the newly created folder 1.0.0.1.
- Build the Manifest file for the server
- Open the Manifest Editor tool that was also installed along with the updater block (Start -> All Programs -> Microsoft Patterns and Practices -> Updater Application Block V2 -> Manifest Editor Tool.
- Under Manifest Properties Tab, click the Generate button and generate the manifest id. Check the Mandatory check box.
- Enter the description �Sample Application Version 1.0.0.1�.
- In the application properties tab, enter the application id as �SampleApplication� and location as �.�
- The entry point is �SampleApplication.exe�.
- The File URI is http://localhost/ApplicationBlockServer/1.0.0.1.
- The source folder is �C:\Inetpub\wwwroot\ApplicationBlockServer\1.0.0.1�.
- Click the �Add� button and select SampleApplication.exe from the 1.0.0.1 folder. The file must appear in the Files list.
- In the activation process tab, enter the process name as AppDeploy and processor type as �Application Deploy� and press �Add�.
- Enter process name as �WFE� and processor type as �Wait For Exit� and press Add. A new window prompts to add a process name. Press Cancel.
- Click the Validate button to validate the generated manifest.
- Click the Save button to Save the manifest at �C:\Inetpub\wwwroot\ApplicationBlockServer� as �ServerManifest.xml�.
- Run the application at �C:\Temp\UpdaterTest�.
The application, after some time, will pops up a dialog box telling that a newer version is available and do you want to download it. Click yes. The newer version will be downloaded which will be displayed in the list box eventList
. After downloading, it will prompt you to restart the application. Close the application and start it again. The version 1.0.0.1 will open up.
Addendum:
- Once the update of the application happens, a folder called UAB gets created in the UpdaterTest folder. This folder gives the information about the latest version present.
- From what I could understand, the manifest ID is maintained at the server and if an update occurs for the client, the manifest ID is placed in the UAB folder. If the manifest ID of the server is different from that of the client (or if the client does not have the UAB folder, meaning no updates have yet taken place), the updater block swings into action.
- To deploy a newer version of the application on the server, create a new folder 1.0.0.2 and dump all the files at that location (the naming convention is just a convention for convenience, not a rule) and generate a new server manifest file with a new Manifest ID and replace the old manifest file.
- I have not checked the auto update feature, i.e. the client can be scheduled to ping the server at regular intervals. But this must be straight forward as setting some property somewhere.
- The code below has a thread to ping the server every 10 seconds. That part can be removed.
Hey, this was just a vanilla implementation.
Auto Update Code to be pasted in the application
#region Auto-Update Stuff
private Thread pollThread = null;
private int manifestDownloaded = 0;
private void CheckAndUpdate()
{
try
{
ApplicationUpdaterManager updater =
ApplicationUpdaterManager.GetUpdater();
updater.DownloadStarted +=
new DownloadStartedEventHandler(updater_DownloadStarted);
updater.DownloadProgress +=
new DownloadProgressEventHandler(updater_DownloadProgress);
updater.DownloadCompleted +=
new DownloadCompletedEventHandler(updater_DownloadCompleted);
updater.DownloadError +=
new DownloadErrorEventHandler(updater_DownloadError);
updater.ActivationInitializing +=
new ActivationInitializingEventHandler(updater_ActivationInitializing);
updater.ActivationStarted +=
new ActivationStartedEventHandler(updater_ActivationStarted);
updater.ActivationInitializationAborted +=
new ActivationInitializationAbortedEventHandler(
updater_ActivationInitializationAborted);
updater.ActivationError +=
new ActivationErrorEventHandler(updater_ActivationError);
updater.ActivationCompleted +=
new ActivationCompletedEventHandler(updater_ActivationCompleted);
Manifest[] manifests = null;
while(true)
{
manifests = updater.CheckForUpdates();
if(manifests.Length > 0)
{
if( MessageBox.Show(this,
"Update for Auto Inproc Application is available,"+
" do you want to apply the update?",
"Update",MessageBoxButtons.YesNo)== DialogResult.Yes)
{
foreach(Manifest m in manifests)
{
m.Apply = true;
}
updater.Download( manifests, TimeSpan.MaxValue );
if(manifestDownloaded == manifests.Length)
{
updater.Activate( manifests );
manifestDownloaded = 0;
}
break;
}
else
{
Thread.Sleep(10000);
}
}
else
{
Thread.Sleep(10000);
}
}
}
catch(ThreadAbortException)
{
}
catch(Exception ex)
{
MessageBox.Show(this,ex.Message,"Error",
MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
private void exitButton_Click(object sender, System.EventArgs e)
{
Application.Exit();
}
private void updater_DownloadStarted(object sender,
DownloadStartedEventArgs e)
{
UpdateList("DownloadStarted for manifest: " + e.Manifest.ManifestId);
}
private void updater_DownloadProgress(object sender,
DownloadProgressEventArgs e)
{
UpdateList("DownloadProgress for manifest: "+ e.Manifest.ManifestId +
"- Files: "+e.FilesTransferred+"/"+e.FilesTotal+
" - Bytes: "+e.BytesTransferred+"/"+e.BytesTotal);
}
private void updater_DownloadCompleted(object sender,
ManifestEventArgs e)
{
UpdateList("DownloadCompleted for manifest: " +
e.Manifest.ManifestId);
manifestDownloaded++;
}
private void updater_DownloadError(object sender,
ManifestErrorEventArgs e)
{
UpdateList("DownloadError for manifest: " +
e.Manifest.ManifestId +"\n"+e.Exception.Message);
}
private void updater_ActivationInitializing(object sender,
ManifestEventArgs e)
{
UpdateList("ActivationInitializing for manifest: " +
e.Manifest.ManifestId);
}
private void updater_ActivationStarted(object sender, ManifestEventArgs e)
{
UpdateList("ActivationStarted for manifest: " + e.Manifest.ManifestId);
}
private void updater_ActivationInitializationAborted(object sender,
ManifestEventArgs e)
{
UpdateList("ActivationInitializationAborted for manifest: " +
e.Manifest.ManifestId);
MessageBox.Show(this,
"The Application needs to restart for applying the updates," +
" please restart the application.",
"Auto Inproc Updates",MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
private void updater_ActivationError(object sender,
ManifestErrorEventArgs e)
{
UpdateList("ActivationError for manifest: " + e.Manifest.ManifestId +
"\n"+e.Exception.Message);
}
private void updater_ActivationCompleted(object sender,
ActivationCompleteEventArgs e)
{
UpdateList("ActivationCompleted for manifest: " + e.Manifest.ManifestId);
}
private void UpdateList(string displayString)
{
eventList.Items.Add(displayString);
eventList.Update();
}
private void InitializeAutoUpdater ()
{
ThreadStart checkUpdateThreadStart = new ThreadStart(CheckAndUpdate);
pollThread = new Thread(checkUpdateThreadStart);
pollThread.Start();
}
#endregion