Generate a self-updated WinForms app with Application Updater Block
BigTall
Original address
In the past two weeks, I have been doing my first real .NET Winform application development. This is a very interesting process, I have been crazy learning. One is what I want. Allow applications to be able to use Microsoft Application Updater Block for self-updating. When it's normal to work, let me have a great sense of accomplishment, and I also realize that Microsoft does not provide that sequential example. Duncan Mackenzie has a good blog article to be a beginning, but this example is VB did and does not provide the details of the RSA public key and private key, so I decided to say my work process. I hope to be useful to you!
Step # 1 Install the Application Blocks
Download The Updater Application Block from Microsoft.
Run the msi installer.
Step # 2 Add code and reference in the project:
Add the following projects to your WINFORM project:
Microsoft.ApplicationBlocks.ApplicationUpdater Microsoft.ApplicationBlocks.ApplicationUpdater.Interfaces Microsoft.ApplicationBlocks.ExceptionManagement Microsoft.ApplicationBlocks.ExceptionManagement.Interfaces
If you choose the default installation, their location may be:
C: / Program Files / Microsoft Application Blocks for .NET / UPDATER / CODE / CS / Microsoft.ApplicationBlocks.Updater
Quote the following projects in your WinForm project
Microsoft.ApplicationBlocks.ApplicationUpdater Microsoft.ApplicationBlocks.ApplicationUpDater.Interfaces Microsoft.ApplicationBlocks.ExceptionManagement
Add the following namespace to your form .cs file
Using system.Runtime.interopservices; using system.runtime.serialization; using system.diagnostics; using system.io; using system.xml;
Then add this location to update the code to your code. You need to call InitializeAutOupDate () from your MainForm initialization method.
Step # 3 Generate your application's publishing directory structure and configure AppStart.exe
Generate a directory for the client program installation. In this example, we use the following directory:
C: / program files / yourapp / 1.0.0.0 /
Copy AppStart.exe and AppStart.exe.config to the following root directory
C: / program files / yourapp / appstart.exe c: / program files / yourapp / appstart.exe.config
Description: These two files You can find "C: / Program Files / Microsoft Application Blocks for .NET / Updater / Code / CS / Microsoft.ApplicationBlocks.Updater / AppStart / Bin / Debug" in the following directory
Step # 4 Modify AppStart.exe.config file AppStart.exe will start your application, if you can restart after the update file download is complete. It needs to know the directory location of your latest program. Modify the configuration file to cooperate with the current version:
STEP # 5: Generate your public key and private key
Run "C: / Program Files / Microsoft Application Blocks for .NET / UPDATER / CODE / CS / Microsoft.ApplicationBlocks.Updater / Manifestutility / Bin / Debug / Manifestutility.exe"
Select "file..generate Keys" will prompt you if you need to save: publickey.xml and privateKey.xml The two key will be used next.
I have to remind everyone that these keys can be generated once, because the following places need to be referenced to the RSA public key and private key. You need to put these keys in a safe place, because it is released a new one It will be used when updating
Step # 6 Create an IIS virtual directory
Generate a directory on your web server to store your update file. In these two directories, you have to put two things 1) ServerManifest.xml files, contain some information about the last version; 2) The directory of your new program. In this directory, generate a directory to store your new version of the program. In our example, we use these two directories, c: / inetpub / appupdates and c: /inetpub/appupdates/1.0.0.1
Generate a virtual directory by IIS Manager to point to the actual directory you just, write down your URL, we need to use it in the upload step. You must open the Directory Browse option of the virtual directory.
Step # 7. Configure your version 1.0.0.0 app.config file here, we need to add some new things in the middle. First, we need to join a configsections element to define our AppUpdater section:
Next, we need to add a Version key to our appsettings, we first set our local version of 1.0.0.0, so we can test the automatic update to version 1.0.0.1
Finally, join the AppUpdater section to your configuration file. I use a pair of brackets to include the value you want to modify. You can copy the
STEP # 8 Release 1.0.0.0 Settings the application version number. You can set the version number by setting the version attribute in the assemblyinfo.cs file.
[Assembly: askMBLYVERSION ("1.0.0.0")]]]]
Compile the application and copy the 1.0.0.0.0.0 directory of the 1.0.0.0.0.0 version of your program. "C: / program files / yourapp / 1.0.0.0"
Here, you need to run AppStart.exe. The update process will fail because we don't have the release serverManifest XML file to indicate if the application new version is available. You can check the log file, location in C: / Program files / yourapp / directory China. Step # 9 Build Version 1.0.0.1 This is the most interesting part. First, by updating the application's assemblyinfo.cs and app.config file content to generate a revised version 1.0.0.1. Compiler, then copy files to step # 6 Generate the web server directory. STEP # 10 Generate the list of servers This is the last step. If you make any modification in this step, you must raise this step again. The practice is as follows:
Run the ManifestUtility program again. Select the 1.0.0.1 directory in the "Update Files Folder" selector. Enter the URL of the update location. Enter the new version number 1.0.0.1 Open the previously generated privatekey.xml file. Select the verification class "Microsoft.ApplicationBlocks. ApplicationUpdater.validators.rsavalidator "Mouse click CreateManifest and saves serverManifest.xml files into your virtual server directory. That's these! Pheew! From your C: / program files / yourapp / directory, run your appstart.exe. You The program will be loaded. When your program is running, you will get a prompt "new version available". The new version will download to the directory C: / program files / yourapp / 1.0.0.1, then the program will Automatic restart. If there is any problem, remember to check the log file. These logs will be useful when diagnostic problems. -Brendan
Posted on Thursday, June 10, 2004 11:25 am
Appendix: The code contained in the text step # 2 is as follows:
Auto-Update Stuff
#region Auto-Update Stuff private ApplicationUpdateManager _updater = null; private Thread _updaterThread = null; private const int UPDATERTHREAD_JOIN_TIMEOUT = 3 * 1000; private delegate void MarshalEventDelegate (object sender, UpdaterActionEventArgs e); private void InitializeAutoUpdate () {// hook ProcessExit for a chance to clean up when closed peremptorily AppDomain.CurrentDomain.ProcessExit = new EventHandler (CurrentDomain_ProcessExit); // make an Updater for use in-process with us _updater = new ApplicationUpdateManager (); // hook 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 = System.Configuration.ConfigurationSettings.AppSettings [ "version" ]; This.text = this.text string.format ("v. {0}", version;} private void currentdomain_processExit (Object sender, Eventargs e) {stopupdater ();} private void stopupdater () {// Tell Updater to stop_Updater.stopupdater (); if (null! =
_updaterThread) {// join the updater thread with a suitable timeout bool isThreadJoined = _updaterThread.Join (UPDATERTHREAD_JOIN_TIMEOUT); // check if we joined, if we did not interrupt the thread if (isThreadJoined) {_updaterThread.Interrupt ()!; } _Updaterthread = null;}} /// This handler gets fas is the main st haked for this form. It takes the time /// arguments as the event Handler Below It - Sender, E - And Acts on the Eventing Thread /// summary> /// Marshalled Reference to the Original Event's sender argument param> /// marshalled reference to the original event's args param> private void OnUpdaterDownloadStartedHandler (object sender, UpdaterActionEventArgs e) {Debug.WriteLine ( "Thread:" Thread.CurrentThread.GetHashCode ( ) .Tostring ()); debug.writeLine (STR ING.FORMAT ("DownloadStarted for Application '{0}'", E.ApplicationName);} / ** ////
MessageBoxButtons.yesno; if (DialogResult.yes == Dialog) {StartNewVersion (E.ServerInformation);}} / ** ////
private void OnUpdaterUpdateAvailableHandler (object sender, UpdaterActionEventArgs e) {Debug.WriteLine ( "Thread:". Thread.CurrentThread.GetHashCode () ToString ()); string message = String.Format ( "Update available: The new version on the server is {0} and current version is {1} would you like to upgrade ", e.ServerInformation.AvailableVersion, System.Configuration.ConfigurationSettings.AppSettings [" version "]);? // for update available we actually WANT to block the downloading thread so we can refuse an update // and reset until next polling cycle; // NOTE that we do not block the thread _in the UI_, we have it blocked at the marshalling dispatcher "OnUpdaterUpdateAvailable" DialogResult dialog = MessageBox.Show ( Message, "Update Available", MessageBoxButtons.yesno; if (DialogResult.no == Dialog) {// if no, stop the updater for this app _Updater.stopupdater (E.ApplicationName); Debug. WriteLine ("Update Cancelle);} else {debug.writeline (" Update in Progress. ");}} / ** //// "E"> the UpdaterActionEventArgs packaged by Updater, which gives us access to update param> private void OnUpdaterUpdateAvailable (object sender, UpdaterActionEventArgs e) {// using the synchronous "Invoke" information This marshals from the eventing thread -. Which comes from the Updater and should not // be allowed to enter and "touch" the UI's window thread // so we use Invoke which allows us to block the Updater thread at will while only allowing window thread to update UI this.Invoke (new MarshalEventDelegate (this.OnUpdaterUpdateAvailableHandler), new object [] {sender, e});} / ** ////