⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 downloader.cs

📁 饭店类的C#程序
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Reflection;
using System.ComponentModel;
using System.Globalization;

namespace Microsoft.Samples.AppUpdater
{
	//**************************************************************
	// AppDownloader class
	// - Responsible for downloading & applying updates.
	//**************************************************************
	public class AppDownloader
	{
		private AppUpdater AppMan;
		private Thread UpdaterThread;
		private AppStartConfig Config;
		private UpdateLog Log;
		private UpdateCompleteEventArgs UpdateEventArgs;
		private AppKeys Keys;

		//Enable checking of downloaded assemblies
		private bool _ValidateAssemblies = false;
		[DefaultValue(false)]
		[Description("Specifies whether or not downloaded assemblies must be signed with valid public keys inorder to be downloaded.")]		 
		public bool ValidateAssemblies
		{
			get {return _ValidateAssemblies;}
			set {_ValidateAssemblies = value;}
		}

		//Delay between download retries when a network problem is encountered
		private int _SecondsBetweenDownloadRetry = 60;
		[DefaultValue(60)]
		[Description("Seconds between download retry attempts.")]
		public int SecondsBetweenDownloadRetry
		{
			get { return _SecondsBetweenDownloadRetry; }
			set { _SecondsBetweenDownloadRetry = value; }
		}

		//Number of times to retry when a download error is encountered
		private int _DownloadRetryAttempts = 3;
		[DefaultValue(3)]
		[Description("Number of times to retry downloads when an error is encountered.")]
		public int DownloadRetryAttempts
		{
			get { return _DownloadRetryAttempts; }
			set { _DownloadRetryAttempts = value; }
		}

		//Number of times to retry the overall update
		private int _UpdateRetryAttempts = 2;
		[DefaultValue(2)]
		[Description("Number of times times to retry the app update.")]
		public int UpdateRetryAttempts
		{
			get { return _UpdateRetryAttempts; }
			set { _UpdateRetryAttempts = value; }
		}

		[Browsable(false)]
		public UpdateState State
		{
			get
			{
				return AppMan.Manifest.State;
			}
		}

		//**************************************************************
		// OnUpdateComplete Event	
		//**************************************************************
		internal delegate void UpdateCompleteEventHandler(object sender, UpdateCompleteEventArgs e);
		internal event UpdateCompleteEventHandler OnUpdateComplete;

		//**************************************************************
		// AppUpdater Constructor	
		//**************************************************************
		public AppDownloader(AppUpdater appMan)
		{
			AppMan = appMan;
			Log = new UpdateLog();
			UpdateEventArgs = new UpdateCompleteEventArgs();
		}

		//**************************************************************
		// Start()	
		//**************************************************************
		public void Start()
		{
			if (UpdaterThread == null) 
				UpdaterThread = new Thread(new ThreadStart(RunThread));
			else if (!UpdaterThread.IsAlive)
				UpdaterThread = new Thread(new ThreadStart(RunThread));

			UpdaterThread.Name="Updater Thread";

			if (!UpdaterThread.IsAlive)
				UpdaterThread.Start();
		}

		//**************************************************************
		// Stop()	
		//**************************************************************
		public void Stop()
		{
			if (UpdaterThread != null && UpdaterThread.IsAlive) 
			{
				UpdaterThread.Abort();
				UpdaterThread = null;
			}
		}

		//**************************************************************
		// RunThread()	
		//**************************************************************
		public void RunThread()
		{
			Debug.WriteLine("APPMANAGER:  Starting Update");

			//Load the AppStart config File
			string ConfigFilePath =Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
			ConfigFilePath = Path.Combine(Directory.GetParent(ConfigFilePath).FullName,"AppStart.config");
			Config = AppStartConfig.Load(ConfigFilePath);

			try 
			{
				//Mark in the manifest that a download is in progress.  Persisted in 
				//manifest in case the app is stop & restarted during the download.
				if (AppMan.Manifest.State.Phase == UpdatePhases.Complete) 
				{
					AppMan.Manifest.State.Phase = UpdatePhases.Scavenging;
					AppMan.Manifest.State.UpdateFailureCount=0;
					AppMan.Manifest.State.UpdateFailureEncoutered = false;
					AppMan.Manifest.State.DownloadDestination = CreateTempDirectory();

					if (AppMan.ChangeDetectionMode == ChangeDetectionModes.ServerManifestCheck)
					{	
						ServerManifest SM = new ServerManifest();
						SM.Load(AppMan.UpdateUrl);
						AppMan.Manifest.State.DownloadSource = SM.ApplicationUrl;
					}
					else 
						AppMan.Manifest.State.DownloadSource = AppMan.UpdateUrl;

					AppMan.Manifest.Update();
				}

				//Scavenge Existing Directories
				if (AppMan.Manifest.State.Phase == UpdatePhases.Scavenging)
				{
					Debug.WriteLine("APPMANAGER:  Scavaging older versions");
					Scavenge();
					AppMan.Manifest.State.Phase=UpdatePhases.Downloading;
					AppMan.Manifest.Update();
				}

				//Download the New Version
				if (AppMan.Manifest.State.Phase == UpdatePhases.Downloading)
				{
					Debug.WriteLine("APPMANAGER:  Downloading new version");
					Download();
					AppMan.Manifest.State.Phase = UpdatePhases.Validating;
					AppMan.Manifest.Update();
				}

				//Validate the downloaded bits
				if (AppMan.Manifest.State.Phase == UpdatePhases.Validating)
				{
					Debug.WriteLine("APPMANAGER:  Downloading new version");
					Validate();
					AppMan.Manifest.State.Phase = UpdatePhases.Merging;
					AppMan.Manifest.Update();
				}

				//Merge the existing version into the new version
				if (AppMan.Manifest.State.Phase == UpdatePhases.Merging)
				{
					Debug.WriteLine("APPMANAGER:  Merging current & new versions");
					MergeDirectory(AppDomain.CurrentDomain.BaseDirectory,AppMan.Manifest.State.DownloadDestination);
					AppMan.Manifest.State.Phase = UpdatePhases.Finalizing;
					AppMan.Manifest.Update();
				}

				//Finalize the update.  Rename the new version directory, etc...
				if (AppMan.Manifest.State.Phase == UpdatePhases.Finalizing)
				{
					Debug.WriteLine("APPMANAGER:  Finalizing update");
					FinalizeUpdate();						
				}

				//Reset Update State
				AppMan.Manifest.State.Phase = UpdatePhases.Complete;
				AppMan.Manifest.State.UpdateFailureCount=0;
				AppMan.Manifest.State.UpdateFailureEncoutered = false;
				AppMan.Manifest.State.DownloadSource = "";
				AppMan.Manifest.State.DownloadDestination = "";
				AppMan.Manifest.State.NewVersionDirectory = "";
				AppMan.Manifest.Update();	
			} 
			catch (ThreadAbortException)
			{
				Thread.ResetAbort();
				Debug.WriteLine("APPMANAGER:  ThreadAborted: Updater Thread stopped, stopping download.");
				return;
			}
			catch (Exception e)
			{
				UpdateEventArgs.FailureException = e;
			}

			if (AppMan.Manifest.State.Phase != UpdatePhases.Complete)
				HandleUpdateFailure();
			else
				HandleUpdateSuccess();
		}

		//**************************************************************
		// HandleUpdateSuccess()	
		//**************************************************************
		private void HandleUpdateSuccess()
		{
			Debug.WriteLine("APPMANAGER:  Update Succeeded");

			try 
			{
				Log.AddSuccess(GetFileVersion(Config.AppExePath));
			} 
			catch (Exception e)
			{
				Debug.WriteLine("APPMANAGER:  Failed to log update success");
				Debug.WriteLine("APPMANAGER:  " + e.ToString());
			}

			//Fire Update Event
			if (OnUpdateComplete != null)
			{
				UpdateEventArgs.UpdateSucceeded = true;
				UpdateEventArgs.NewVersion = new Version(GetFileVersion(Config.AppExePath));
				if (UpdateEventArgs.ErrorMessage == "")
					UpdateEventArgs.ErrorMessage = "Unknown Error";
				OnUpdateComplete(this, UpdateEventArgs);
			}
		}

		//**************************************************************
		// HandleUpdateFailure()	
		//**************************************************************
		private void HandleUpdateFailure()
		{
			Debug.WriteLine("APPMANAGER:  Update Failed");

			try 
			{
				Log.AddError(UpdateEventArgs.FailureException.ToString());
			} 
			catch (Exception e)
			{
				Debug.WriteLine("APPMANAGER:  Failed to log update failure");
				Debug.WriteLine("APPMANAGER:  " + e.ToString());
			}

			AppMan.Manifest.State.UpdateFailureEncoutered = true;
			AppMan.Manifest.State.UpdateFailureCount++;
			AppMan.Manifest.Update();

			//If the update has failed too many times
			if (AppMan.Manifest.State.UpdateFailureCount >= UpdateRetryAttempts)
			{
				Debug.WriteLine("APPMANAGER:  Updated Failed 2 times.  Reseting Manifest");
				AppMan.Manifest.State.Phase = UpdatePhases.Complete;
				AppMan.Manifest.State.UpdateFailureEncoutered = false;
				AppMan.Manifest.State.UpdateFailureCount = 0;
				AppMan.Manifest.State.DownloadSource = "";
				AppMan.Manifest.State.DownloadDestination = "";				
				AppMan.Manifest.Update();
			}

			if (OnUpdateComplete != null)
			{
				UpdateEventArgs.UpdateSucceeded = false;
				if (UpdateEventArgs.ErrorMessage == "")
					UpdateEventArgs.ErrorMessage = "Unknown Error";
				OnUpdateComplete(this, UpdateEventArgs);
			}
		}

		//**************************************************************
		// Download()	
		//**************************************************************
		private void Download()
		{
			bool DownloadInProgress = true;
			int DownloadAttemptCount = 0;
			int SecondsToSleep = 0;

			while (DownloadInProgress)
			{
				Thread.Sleep(TimeSpan.FromSeconds(SecondsToSleep));
				SecondsToSleep = SecondsBetweenDownloadRetry;

				DownloadAttemptCount++;

				Trace.WriteLine("APPMANAGER:  Attempting to download update from:  " + AppMan.Manifest.State.DownloadSource);

				try
				{
					int UpdateCount = WebFileLoader.CopyDirectory(AppMan.Manifest.State.DownloadSource,AppMan.Manifest.State.DownloadDestination); 
					Debug.WriteLine("APPMANAGER:  Number of files updated from the server:  " + UpdateCount);

					Debug.WriteLine("APPMANAGER:  App update downloaded successfully");

					DownloadInProgress = false;
				} 
					//Things that could go wrong while downloading are pretty much any kind of 
					//network problem, like the client just going offline.  However, this can cause
					//itself to manifest in any number of ways... like exceptions on the stream
					//objects used to copy the file to disk.
				catch (WebException e)
				{
					Debug.WriteLine("APPMANAGER:  Update download failed due to network exception:");
					Debug.WriteLine("APPMANAGER:  " + e.ToString());
					
					if (DownloadAttemptCount >= DownloadRetryAttempts)
					{
						Debug.WriteLine("APPMANAGER:  Download attempt has failed 3 times.  Aborting Update");
						UpdateEventArgs.ErrorMessage = "Download of a new update from '"+ AppMan.Manifest.State.DownloadSource 
							+"' failed with the network error:  " + e.Message;
						throw e;
					}
				}
				catch (IOException e)
				{
					Debug.WriteLine("APPMANAGER:  Update download failed due to file I/O exception:");
					Debug.WriteLine("APPMANAGER:  " + e.ToString());
					
					if (DownloadAttemptCount >= DownloadRetryAttempts)
					{
						Debug.WriteLine("APPMANAGER:  Download attempt has failed 3 times.  Aborting Update");
						UpdateEventArgs.ErrorMessage = "Saving the new update to disk at '" + AppMan.Manifest.State.DownloadDestination 
							+"' failed with the following error:  " + e.Message;
						throw e;
					}
				}
				catch (Exception e)
				{
					Debug.WriteLine("APPMANAGER:  Update download failed due to the following error:  " + e.Message);
					Debug.WriteLine("APPMANAGER:  " + e.ToString());
					
					if (DownloadAttemptCount >= DownloadRetryAttempts)
					{
						Debug.WriteLine("APPMANAGER:  Download attempt has failed 3 times.  Aborting Update");
						UpdateEventArgs.ErrorMessage = "Update failed with the following error:  '"+ e.Message + "'";
						throw e;
					}
				}
			}
		}

		//**************************************************************
		// Validate()	
		//**************************************************************
		private void Validate()
		{
			if (!ValidateAssemblies)
				return;

			//Initialize the Keys Object
			Keys = new AppKeys(AppMan.Manifest.State.DownloadSource);
			Keys.InitializeKeyCheck();

			try 
			{
				ValidateDirectory(AppMan.Manifest.State.DownloadDestination);
			} 
			catch (Exception)
			{
				Keys.UnInitializeKeyCheck();

				//Remove the downloaded files if any error occurs in validation.
				HardDirectoryDelete(AppMan.Manifest.State.DownloadDestination);

				//Set the update failure count to max.
				//Don't retry the update another time.  This will cause the update
				//to reset.
				AppMan.Manifest.State.UpdateFailureCount = UpdateRetryAttempts;
				AppMan.Manifest.Update();  
				throw;
			}

			Keys.UnInitializeKeyCheck();
		}


		//**************************************************************
		// ValidateDirectory()	
		//**************************************************************
		private void ValidateDirectory(string source)
		{
			try 
			{
				//Get a reference to the source directory
				DirectoryInfo Source = new DirectoryInfo(source);
			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -