| ÔÚ¹ýÈ¥µÄÁ½¸öÐÇÆÚÀï, ÎÒÒ»Ö±ÔÚ×öÎҵĵÚÒ»¸öÕæÕýµÄ.net WinFormÓ¦ÓõĿª·¢. ÕâÊÇÒ»¸öºÜÓÐȤµÄ¹ý³Ì,ÎÒÒ»Ö±ÔÚ·èÁËËÆµÄѧϰ¶«Î÷. ÆäÖÐÖ®Ò»¾ÍÊÇÎÒÒªÔÊÐíÓ¦ÓóÌÐòÄܹ»ÓÃ΢ÈíµÄApplication Updater Block½øÐÐ×ÔÎÒ¸üС£ µ±ËüÕý³£¹¤×÷µÄÄÇÒ»¿Ì£¬ÈÃÎÒÓÐÒ»ÖֺܴóµÄ³É¾Í¸Ð£¬Í¬Ê±ÎÒÒ²Òâʶµ½Î¢ÈíûÓÐÌṩÄÇÖÖ°´²½Öè˳ÐòµÄÀý×Ó¡£ Duncan Mackenzie ÓÐÒ»¸ö ºÜºÃµÄblogÎÄÕ ¿ÉÒÔ×öÒ»¸ö¿ªÊ¼£¬µ«ÊÇÕâ¸öÀý×ÓÊÇVB×öµÄ²¢ÇÒûÓÐÌṩRSA¹«Ô¿ºÍ˽ԿµÄϸ½ÚÇé¿ö£¬ËùÒÔÎÒ¾ö¶¨ËµÒ»ÏÂÎҵŤ×÷¹ý³Ì¡£ Ï£ÍûÄܶÔÄãÓÐÓã¡
Step #1 Install the Application Blocks
Download the Updater Application Block from Microsoft .
Run the MSI Installer.
Step #2 ÔÚÏîÄ¿ÖмÓÈë´úÂëºÍÒýÓÃ:
°ÑÏÂÁй¤³Ì¼ÓÈëµ½ÄãµÄWinForm¹¤³ÌËùÔڵĽâ¾ö·½°¸:
Microsoft.ApplicationBlocks.ApplicationUpdater Microsoft.ApplicationBlocks.ApplicationUpdater.Interfaces Microsoft.ApplicationBlocks.ExceptionManagement Microsoft.ApplicationBlocks.ExceptionManagement.Interfaces
Èç¹ûÄãÑ¡ÔñĬÈϰ²×°µÄ»°£¬ËüÃǵÄλÖÿÉÄÜÊÇ£º
C:\Program Files\Microsoft Application Blocks for .NET\Updater\Code\CS\Microsoft.ApplicationBlocks.Updater
ÔÚÄãµÄWinForm¹¤³ÌÖÐÒýÓÃÏÂÁй¤³Ì
Microsoft.ApplicationBlocks.ApplicationUpdater Microsoft.ApplicationBlocks.ApplicationUpdater.Interfaces Microsoft.ApplicationBlocks.ExceptionManagement
°ÑÏÂÁÐÃüÃû¿Õ¼ä¼ÓÈëµ½ÄãFormµÄ.csÎļþÖÐ
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Xml;
È»ºó Ìí¼ÓÕâ¸öλÖõÄÓ¦ÓóÌÐò¸üдúÂëµ½ÄãµÄ´úÂëÖÐ. ÄãÐèÒª´ÓÄãµÄMainForm³õʼ»¯·½·¨Öе÷Óà InitializeAutoUpdate()¡£
Step #3 Éú³ÉÄãÓ¦ÓóÌÐòµÄ·¢²¼Ä¿Â¼½á¹¹²¢ÅäÖà AppStart.exe
Éú³ÉÒ»¸öÓÃÓÚ¿Í»§¶Ë³ÌÐò°²×°µÄĿ¼. ±¾Àý×ÓÖУ¬ÎÒÃÇÓÃÈçϵÄĿ¼£º
C:\Program Files\YourApp\1.0.0.0\
ÏÖÔÚ¸´ÖÆ AppStart.exe ºÍ AppStart.exe.config µ½ÀàËÆÈçϵĸùĿ¼ÖÐ
C:\Program Files\YourApp\AppStart.exe C:\Program Files\YourApp\AppStart.exe.config
˵Ã÷: ÕâÁ½¸öÎļþÄã¿ÉÒÔÔÚÈçÏÂĿ¼ÖÐÕÒµ½ ¡°C:\Program Files\Microsoft Application Blocks for .NET\Updater\Code\CS\Microsoft.ApplicationBlocks.Updater\AppStart\bin\Debug¡°
Step #4 ÐÞ¸Ä AppStart.exe.config Îļþ
AppStart.exe »áÆô¶¯ÄãµÄÓ¦ÓóÌÐò£¬Èç¹û¸üÐÂÎļþÏÂÔØÍê³ÉÖ®ºó»¹ÓпÉÄÜÒªÖØÆô. ËüÐèÒªÖªµÀÆô¶¯Äã×îеijÌÐòµÄĿ¼λÖÃ. ÐÞ¸ÄÅäÖÃÎļþÒÔÅäºÏµ±Ç°µÄ°æ±¾:
<appStart>
<ClientApplicationInfo>
<appFolderName>C:Program FilesYourApp1.0.0.0</appFolderName>
<appExeName>YourAppName.exe</appExeName>
<installedVersion>1.0.0.0</installedVersion>
<lastUpdated>2004-06-10T15:33:17.3745836-04:00</lastUpdated>
</ClientApplicationInfo>
</appStart>
Step #5: Éú³ÉÄãµÄ¹«Ô¿ºÍ˽Կ
ÔËÐÐ "C:\Program Files\Microsoft Application Blocks for .NET\Updater\Code\CS\Microsoft.ApplicationBlocks.Updater\ManifestUtility\bin\Debug\ManifestUtility.exe"
Ñ¡Ôñ ¡°File..Generate Keys¡± »áÌáʾÄãÊÇ·ñÐèÒª±£´æ: PublicKey.xml ºÍ PrivateKey.xml ÕâÁ½¸öÃÜÔ¿½ÓÏÂÀ´¾Í»áÓõ½.
ÎÒÕâÀïÒªÌáÐÑ´ó¼Ò£¬ÕâЩÃÜÔ¿Ö»ÒªÉú³ÉÒ»´Î¾Í¿ÉÒÔÁË, ÒòΪÏÂÃæ¼¸¸öµØ·½ÐèÒªÒýÓõ½RSA¹«Ô¿ºÍ˽Կ. ÄãÐèÒª°ÑÕâЩÃÜÔ¿´æ·ÅÔÚÒ»¸ö°²È«µÄµØ·½£¬ÒòΪÔÚ·¢²¼Ò»¸öеĸüеÄʱºò»áÓõ½Ëü
Step #6 ´´½¨IIS ÐéÄâĿ¼
ÔÚÄãµÄWeb·þÎñÆ÷ÉÏÉú³ÉÒ»¸öĿ¼À´´æ·ÅÄãµÄ¸üÐÂÎļþ. ÔÚÕâÁ½¸öĿ¼ÖÐÒª·ÅÁ½Ñù¶«Î÷ 1) ServerManifest.xml Îļþ£¬°üº¬×îºó°æ±¾µÄһЩÐÅÏ¢£»2) ÄãµÄгÌÐòµÄĿ¼. ÔÚÕâ¸öĿ¼ÀÉú³ÉÒ»¸öĿ¼À´´æ·ÅÄãµÄа汾³ÌÐò. ÔÚÎÒÃǵÄÀý×ÓÖУ¬ÎÒÃÇÓÃÕâÁ½¸öĿ¼, C:\Inetpub\AppUpdates ºÍC:\Inetpub\AppUpdates\1.0.0.1
Óà IIS ¹ÜÀíÆ÷Éú³ÉÒ»¸öÐéÄâĿ¼ָÏò¸Õ²ÅµÄʵ¼ÊĿ¼. ¼ÇÏÂÄãµÄ URL, ÔÚÉÏ´«²½ÖèÖÐÎÒÃÇÐèÒªÓõ½Ëü. Äã±ØÐëÒª´ò¿ªÐéÄâĿ¼µÄ¡°Ä¿Â¼ä¯ÀÀ¡±Ñ¡Ïî.
Step #7. ÅäÖÃÄãµÄ°æ±¾ 1.0.0.0 µÄApp.config Îļþ
ÕâÀÎÒÃÇ»áÐèÒªÍùÀïÌí¼ÓһЩж«Î÷. Ê×ÏÈ, ÎÒÃÇÐèÒª¼ÓÈëÒ»¸öconfigSections ÔªËØÀ´¶¨ÒåÎÒÃÇµÄ appUpdater ½Ú:
<configSections> <section name="appUpdater" type="Microsoft.ApplicationBlocks.ApplicationUpdater.UpdaterSectionHandler,Microsoft.ApplicationBlocks.ApplicationUpdater" /> </configSections>
½ÓÏÂÀ´£¬ÎÒÃÇÐèÒªÌí¼ÓÒ»¸ö Version ¼üµ½ÎÒÃÇµÄ appsettings ÖÐ, ÎÒÃÇÊ×ÏÈÉèÖÃÎÒÃǵı¾µØ°æ±¾Îª 1.0.0.0, ÕâÑùÎÒÃǾͿÉÒÔ²âÊÔ×Ô¶¯¸üе½°æ±¾ 1.0.0.1
<appSettings> <add key="VERSION" value="1.0.0.0" /> </appSettings>
×îºó£¬, ¼ÓÈë appUpdater ½Úµ½ÄãµÄÅäÖÃÎļþÖÐ. ÎÒÕâÀïÓÃÒ»¶Ô·½À¨ºÅ°ÑÄãÒªÐ޸ĵÄÖµ°üº¬ÆðÀ´. Äã¿ÉÒÔÖ±½Ó´ÓÄãÉÏÒ»²½Éú³ÉµÄ PublicKey.xmlÎļþÖи´ÖÆ <RSAKeyValue> ÔªËØ.
<xmlFile> ÔªËØ±ØÐëÒªÖ¸ÏòÄãÔÚStep #6´´½¨µÄÐéÄâĿ¼µÄ URL .
<appUpdater>
<UpdaterConfiguration>
<polling type="Seconds" value="120" />
<logListener logPath="C:Program FilesYourAppUpdaterLog.txt" />
<downloader type="Microsoft.ApplicationBlocks.ApplicationUpdater.Downloaders.BITSDownloader"
assembly="Microsoft.ApplicationBlocks.ApplicationUpdater,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
<validator type="Microsoft.ApplicationBlocks.ApplicationUpdater.Validators.RSAValidator" assembly="Microsoft.ApplicationBlocks.ApplicationUpdater,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null">
<key>
<RSAKeyValue>
<Modulus>[YOUR MODULUS KEY]</Modulus>
<Exponent>[YOUR EXPONENET]</Exponent>
</RSAKeyValue>
</key>
</validator>
<application name="[YOUR APP NAME]" useValidation="true">
<client>
<baseDir>C:Program FilesYourApp</baseDir>
<xmlFile>C:Program FilesYourAppAppStart.exe.config</xmlFile>
<tempDir>C:Program FilesYourApp emp</tempDir>
</client>
<server>
<xmlFile>http://[YOUR URL]/ServerManifest.xml</xmlFile>
<xmlFileDest>C:Program FilesYourAppServerManifest.xml</xmlFileDest>
<maxWaitXmlFile>60000</maxWaitXmlFile>
</server>
</application>
</UpdaterConfiguration>
</appUpdater>
Step #8 ·¢²¼°æ±¾ 1.0.0.0
ÉèÖÃÓ¦ÓóÌÐò°æ±¾ºÅ. ¿ÉÒÔͨ¹ýÉèÖÃÔÚ AssemblyInfo.cs ÎļþÖеİ汾ÊôÐÔÀ´ÉèÖð汾ºÅ.
[assembly: AssemblyVersion("1.0.0.0")]
±àÒëÓ¦ÓóÌÐò²¢¸´ÖÆ 1.0.0.0 °æ³ÌÐòµ½Äã³ÌÐòµÄ 1.0.0.0 Ŀ¼ÖÐ. ¡°C:\Program Files\YourApp\1.0.0.0¡°
ÕâÀÄãÐèÒªÔËÐÐһϠAppStart.exe. ¸üйý³Ì»áʧ°Ü£¬ÒòΪÎÒÃDz¢Ã»Óаѷ¢²¼ ServerManifest XML ÎļþÀ´Ö¸Ê¾Ó¦ÓóÌÐòа汾ÊÇ·ñ¿ÉÓÃ. Äã¿ÉÒÔ¼ì²éÈÕÖ¾Îļþ£¬Î»ÖÃÔÚ C:\Program Files\YourApp\ Ŀ¼ÖÐ.
Step #9 ¹¹½¨°æ±¾ 1.0.0.1
ÕâÊÇ×îÓÐȤµÄ²¿·Ö. Ê×ÏÈ, ͨ¹ý¸üÐÂÓ¦ÓóÌÐòµÄ AssemblyInfo.cs ºÍ App.config ÎļþÄÚÈÝÀ´Éú³ÉÐÞ¶©°æ±¾ 1.0.0.1 . ±àÒë³ÌÐò, È»ºó¸´ÖÆÎļþµ½step #6Éú³ÉµÄWeb·þÎñÆ÷Ŀ¼ÖÐ.
Step #10 Éú³É·þÎñÆ÷µÄÇåµ¥Îļþ
Õâ¸öÊÇ×îºóÒ»²½. Èç¹ûÄã¶Ô±¾²½ÖèÖеÄ.configÎļþ×÷ÁËÈκÎÐ޸ĵϰ£¬¶¼±ØÐë°Ñ±¾²½ÖèÖØÀ´Ò»±é. ×ö·¨ÈçÏÂ:
ÔÙ´ÎÔËÐÐ ManifestUtility ³ÌÐò. ÔÚ ¡°Update files folder¡° Ñ¡ÔñÆ÷ÖÐÑ¡Ôñ 1.0.0.1 Ŀ¼ . ÊäÈë¸üÐÂλÖÃµÄ URL . ÊäÈëа汾ºÅ 1.0.0.1 ´ò¿ªÖ®Ç°Éú³ÉµÄ PrivateKey.xml Îļþ. Ñ¡ÔñÑéÖ¤Àà ¡°Microsoft.ApplicationBlocks.ApplicationUpdater.Validators.RSAValidator¡± Êó±êµã»÷ CreateManifest, ²¢±£´æ ServerManifest.xml Îļþµ½ÄãµÄÐéÄâ·þÎñÆ÷Ŀ¼ÖÐ. ¾ÍÕâЩ! Pheeew! ´ÓÄãµÄ C:\Program Files\YourApp\ Ŀ¼ÖÐÔËÐÐÄãµÄ AppStart.exe . ÄãµÄ³ÌÐò¾Í»á±»×°Èë, µ±ÄãµÄ³ÌÐòÔËÐеÄʱºò£¬Äã¾Í»áµÃµ½Ò»¸öÌáʾ ¡°Ð°汾¿ÉÓá± . а汾»áÏÂÔØµ½Ä¿Â¼ C:\Program Files\YourApp\1.0.0.1 ÖÐ, È»ºó³ÌÐò»á×Ô¶¯ÖØÆô. Èç¹ûÓÐÈκÎÎÊÌâ, ¼ÇµÃ¼ì²éÒ»ÏÂÈÕÖ¾Îļþ. ÕâЩÈÕÖ¾ÔÚÕï¶ÏÎÊÌâµÄʱºò»áºÜÓÐÓõÄ.
-Brendan
posted on Thursday, June 10, 2004 11:25 AM
¸½Â¼£ºÎÄÖв½Öè #2 °üº¬µÄ´úÂëÈçÏ£º
 Auto-Update StuffAuto-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 didn't interrupt the thread
if( !isThreadJoined )
 ...{
_updaterThread.Interrupt();
}
_updaterThread = null;
}
}
 /**//**//**//// <summary>
/// This handler gets fired by the Windows UI thread that is the main STA thread for THIS FORM. It takes the same
/// arguments as the event handler below it--sender, e--and acts on them using the main thread NOT the eventing thread
/// </summary>
/// <param name="sender">marshalled reference to the original event's sender argument</param>
/// <param name="e">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(String.Format( " DownloadStarted for application '{0}'", e.ApplicationName ));
}
 /**//**//**//// <summary>
/// Event handler for Updater event. This event is fired by the originating thread from "inside" the Updater. While it is
/// possible for this same thread to act on our UI, it is NOT a good thing to do--UI is not threadsafe.
/// Therefore here we marshal from the Eventing thread (belongs to Updater) to our window thread using the synchronous Invoke
/// mechanism.
/// </summary>
/// <param name="sender">event sender in this case ApplicationUpdaterManager</param>
/// <param name="e">the UpdaterActionEventArgs packaged by Updater, which gives us access to update information</param>
private void OnUpdaterDownloadStarted( object sender, UpdaterActionEventArgs e )
 ...{
// using the synchronous "Invoke". 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
Debug.WriteLine( String.Format( "[OnUpdaterDownloadStarted]Thread: {0}", Thread.CurrentThread.GetHashCode().ToString()) );
this.Invoke(
new MarshalEventDelegate( this.OnUpdaterDownloadStartedHandler ),
 new object[] ...{ sender, e } );
}
 /**//**//**//// <summary>
/// This handler gets fired by the Windows UI thread that is the main STA thread for THIS FORM. It takes the same
/// arguments as the event handler below it--sender, e--and acts on them using the main thread NOT the eventing thread
/// </summary>
/// <param name="sender">marshalled reference to the original event's sender argument</param>
/// <param name="e">marshalled reference to the original event's args</param>
private void OnUpdaterFilesValidatedHandler( object sender, UpdaterActionEventArgs e )
 ...{
Debug.WriteLine(String.Format("FilesValidated successfully for application '{0}' ", e.ApplicationName));
// 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 );
}
}
 /**//**//**//// <summary>
/// Event handler for Updater event. This event is fired by the originating thread from "inside" the Updater. While it is
/// possible for this same thread to act on our UI, it is NOT a good thing to do--UI is not threadsafe.
/// Therefore here we marshal from the Eventing thread (belongs to Updater) to our window thread using the synchronous Invoke
/// mechanism.
/// </summary>
/// <param name="sender">event sender in this case ApplicationUpdaterManager</param>
/// <param name="e">the UpdaterActionEventArgs packaged by Updater, which gives us access to update information</param>
private void OnUpdaterFilesValidated( object sender, UpdaterActionEventArgs e )
 ...{
// using the asynchronous "BeginInvoke".
// we don't need/want to block here
this.BeginInvoke(
new MarshalEventDelegate( this.OnUpdaterFilesValidatedHandler ),
 new object[] ...{ sender, e } );
}
 /**//**//**//// <summary>
/// This handler gets fired by the Windows UI thread that is the main STA thread for THIS FORM. It takes the same
/// arguments as the event handler below it--sender, e--and acts on them using the main thread NOT the eventing thread
/// </summary>
/// <param name="sender">marshalled reference to the original event's sender argument</param>
/// <param name="e">marshalled reference to the original event's args</param> 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 don't 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 Cancelled.");
}
else
 ...{
Debug.WriteLine("Update in progress.");
}
}
 /**//**//**//// <summary>
/// Event handler for Updater event. This event is fired by the originating thread from "inside" the Updater. While it is
/// possible for this same thread to act on our UI, it is NOT a good thing to do--UI is not threadsafe.
/// Therefore here we marshal from the Eventing thread (belongs to Updater) to our window thread using the synchronous Invoke
/// mechanism.
/// </summary>
/// <param name="sender">event sender in this case ApplicationUpdaterManager</param>
/// <param name="e">the UpdaterActionEventArgs packaged by Updater, which gives us access to update information</param> private void OnUpdaterUpdateAvailable( object sender, UpdaterActionEventArgs e )
 ...{
// using the synchronous "Invoke". 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 } );
}
 /**//**//**//// <summary>
/// This handler gets fired by the Windows UI thread that is the main STA thread for THIS FORM. It takes the same
/// arguments as the event handler below it--sender, e--and acts on them using the main thread NOT the eventing thread
/// </summary>
/// <param name="sender">marshalled reference to the original event's sender argument</param>
/// <param name="e">marshalled reference to the original event's args</param> private void OnUpdaterDownloadCompletedHandler( object sender, UpdaterActionEventArgs e )
 ...{
Debug.WriteLine("Download Completed.");
}
 /**//**//**//// <summary>
/// Event handler for Updater event. This event is fired by the originating thread from "inside" the Updater. While it is
/// possible for this same thread to act on our UI, it is NOT a good thing to do--UI is not threadsafe.
/// Therefore here we marshal from the Eventing thread (belongs to Updater) to our window thread using the synchronous Invoke
/// mechanism.
/// </summary>
/// <param name="sender">event sender in this case ApplicationUpdaterManager</param>
/// <param name="e">the UpdaterActionEventArgs packaged by Updater, which gives us access to update information</param> private void OnUpdaterDownloadCompleted( object sender, UpdaterActionEventArgs e )
 ...{
// using the synchronous "Invoke". 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.OnUpdaterDownloadCompletedHandler ),
 new object[] ...{ sender, e } );
}
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 );
}
|