Click here to Skip to main content
15,895,793 members
Articles / Programming Languages / C#

The Razor Framework :: Part 1 :: Plugins/Extensibility

Rate me:
Please Sign up or sign in to vote.
4.93/5 (127 votes)
11 Mar 2005CPOL36 min read 352K   1.4K   446  
An extensible dependency based plugin framework for .NET Applications.
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading;
using Razor;

namespace Razor.Networking.AutoUpdate.Common
{
	/// <summary>
	/// Summary description for AutoUpdateDownloader.
	/// </summary>
	public class AutoUpdateDownloader
	{
		protected string _id;
		protected int _segmentSize;
		public const int DefaultSegmentSize = 8192;

		/// <summary>
		/// Initializes a new instance of the AutoUpdateDownloader class
		/// </summary>
		public AutoUpdateDownloader()
		{
			_id = Guid.NewGuid().ToString();
			_segmentSize = DefaultSegmentSize;
		}

		#region My Public Properties

		/// <summary>
		/// Gets or sets the unique identier associated with this AutoUpdate Manger
		/// </summary>	
		public string Id
		{
			get
			{
				return _id;
			}
			set
			{
				_id = value;
			}
		}
		
		/// <summary>
		/// Gets or sets the segment size used during downloading
		/// </summary>
		public int SegmentSize
		{
			get
			{
				return _segmentSize;
			}
			set
			{
				_segmentSize = value;
			}
		}

		#endregion

		#region My Public Virtual Methods

		/// <summary>
		/// Instructs the AutoUpdateDownloader to query for the latest version available 
		/// </summary>
		/// <param name="progressViewer">The progress viewer by which progress should be displayed</param>
		/// <param name="options">The options that affect this downloader</param>
		/// <param name="productToUpdate">The product descriptor for the product that should be updated</param>
		/// <param name="updateAvailable">The download descriptor that describes the download that could potentially occur</param>
		/// <returns></returns>
		public virtual bool QueryLatestVersion(
			IProgressViewer progressViewer,
			AutoUpdateOptions options,
			AutoUpdateProductDescriptor productToUpdate, 
			out AutoUpdateDownloadDescriptor updateAvailable)
		{			
			updateAvailable = null;

			return false;							
		}
		
		/// <summary>
		/// Instructs the AutoUpdateDownloader to download the update specified by the update descriptor
		/// </summary>
		/// <param name="progressViewer">The progress viewer by which progress should be displayed</param>
		/// <param name="downloadDescriptor">The download descriptor that describes the download that should occur</param>
		/// <returns></returns>
		public virtual bool Download(
			IProgressViewer progressViewer,
			AutoUpdateDownloadDescriptor downloadDescriptor)
		{
			FileStream localStream = null;
			Stream remoteStream = null;
			string myTraceCategory = string.Format("'{0}'", this.GetType().Name);

			try
			{
				// set the progress to zero for the start
				this.SetDownloadProgress(progressViewer, 0, downloadDescriptor.Manifest.SizeOfUpdate);

				// format the downloaded path where the .update file will be when the download is finished				
				downloadDescriptor.DownloadedPath = Path.Combine(downloadDescriptor.Options.DownloadPath, Path.GetFileName(downloadDescriptor.Manifest.UrlOfUpdate));

				Debug.WriteLine(string.Format("Preparing to download update.\n\tThe update will be downloaded from '{0}'.\n\tThe update will be downloaded to '{1}'.", downloadDescriptor.Manifest.UrlOfUpdate, downloadDescriptor.DownloadedPath), myTraceCategory);
				
				// if the url where this update is supposed to be located is not set, just quit as there isn't anything else we can do
				if (downloadDescriptor.Manifest.UrlOfUpdate == null || downloadDescriptor.Manifest.UrlOfUpdate == string.Empty)
					return false;

				// create a new web client to download the file
				WebClient wc = new WebClient();

				// open a remote stream to the download
				Debug.WriteLine(string.Format("Preparing to download update.\n\tOpening stream to the remote url '{0}'.", downloadDescriptor.Manifest.UrlOfUpdate), myTraceCategory);
				remoteStream = wc.OpenRead(downloadDescriptor.Manifest.UrlOfUpdate);

				// open a local file stream where the update will be downloaded
				Debug.WriteLine(string.Format("Preparing to download update.\n\tOpening stream to the local url '{0}'.", downloadDescriptor.DownloadedPath), myTraceCategory);
				localStream = new FileStream(downloadDescriptor.DownloadedPath, FileMode.Create, FileAccess.Write, FileShare.None);

				// if successfull we'll receive the data in segments
				if (remoteStream != null)
				{
					long bytesDownloaded = 0;
					while (true)
					{
						// figure out how many bytes we have to download
						long bytesToReceive = downloadDescriptor.Manifest.SizeOfUpdate - bytesDownloaded;

						// correct it if it's more than the segment size
						if (bytesToReceive > _segmentSize)
							bytesToReceive = (long)_segmentSize;

						byte[] segment = new byte[bytesToReceive];

						// read a segment off the socket
						int bytesReceived = remoteStream.Read(segment, 0, (int)bytesToReceive);

						// bail if nothing read
						if (bytesReceived == 0)
							break;

						// if we received anything
						if (bytesReceived > 0)
						{
							// write it to the update file
							localStream.Write(segment, 0, bytesReceived);
							// update the position
							bytesDownloaded += bytesReceived;
						}

						// update the progress viewer
						this.SetDownloadProgress(progressViewer, bytesDownloaded, downloadDescriptor.Manifest.SizeOfUpdate);
					}
				}

				Debug.WriteLine(string.Format("The update was successfully downloaded to '{0}'.", downloadDescriptor.DownloadedPath), myTraceCategory);

				return true;
			}
			catch(ThreadAbortException)
			{

			}
			catch(Exception ex)
			{							
				try 
				{ 
					if (localStream != null) 
						localStream.Close(); 

					if (remoteStream != null) 
						remoteStream.Close();
				} 
				catch(Exception)
				{
				
				}

				try
				{
					// something broke, make sure we delete the .update file
					File.Delete(downloadDescriptor.DownloadedPath);
				}
				catch(Exception)
				{

				}

				throw ex;
			}
			finally
			{
				/* 
				 * make sure the streams are closed
				 * */

				try 
				{ 
					if (localStream != null) localStream.Close(); 
					if (remoteStream != null) remoteStream.Close();
				} 
				catch {}

				try
				{
					
				}
				catch {}
			}

			// if it's made it this far something went wrong
			return false;

		}
		
		/// <summary>
		/// Instructs the AutoUpdateDownloader to cleanup after an install
		/// </summary>
		/// <param name="progressViewer">The progress viewer by which progress should be displayed</param>
		/// <param name="downloadDescriptor">The download descriptor that describes the download that occurred and was installed</param>
		public virtual bool FinalizeInstallation(			
			IProgressViewer progressViewer,
			AutoUpdateDownloadDescriptor downloadDescriptor)
		{
			return true;			
		}

		/// <summary>
		/// Formats the bytes into a more readable string format using KB instead of bytes
		/// </summary>
		/// <param name="dwFileSize"></param>
		/// <returns></returns>
		public virtual string FormatFileLengthForDisplay(long dwFileSize)
		{
			decimal fileSize = 0;
			if (dwFileSize > 0)
			{
				fileSize = Convert.ToDecimal(dwFileSize / 1000.0);
				fileSize = Math.Round(fileSize);
				fileSize = Math.Max(1, fileSize);
			}

			int fileSizeInt = Convert.ToInt32(fileSize);
			return fileSizeInt.ToString("###,###,##0") + " KB";	
		}

		/// <summary>
		/// Updates the display of the specified progress dialog
		/// </summary>
		/// <param name="progressViewer"></param>
		/// <param name="bytesReceived"></param>
		/// <param name="bytesTotal"></param>
		public virtual void SetDownloadProgress(IProgressViewer progressViewer, long bytesReceived, long bytesTotal)
		{								
			double p = ((double)bytesReceived / (double)bytesTotal) * 100;
			int percent = (int)p;
			
			string title = string.Format("AutoUpdate Progress..." + "({0}% Completed)", percent.ToString());
			string received = this.FormatFileLengthForDisplay(bytesReceived);
			string total = this.FormatFileLengthForDisplay(bytesTotal);
			string description = string.Format("Progress: ({0} of {1} downloaded)", received, total);

			ProgressViewer.SetTitle(progressViewer, title);
			ProgressViewer.SetExtendedDescription(progressViewer, description);							
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Senior Application Developer specializing in Windows desktop and network development.

Professional Experience
- B.S. of Computer Science (Graduated 2001 - PSU)
- Senior Application Developer (8+ yrs)
- Microsoft Certified Professional

Primary Interests
- C#, C++, HTML, Javascript
- XML, ASP.NET, Web Services, SOAP, UDDI
- Socket programming and anything network related
- Reflection, Serialization, and Plugin Frameworks
- Owner-drawn controls and GDI+ goodness

Comments and Discussions