/// <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 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 override bool QueryLatestVersion(IProgressViewer progressViewer, AutoUpdateOptions options, AutoUpdateProductDescriptor productToUpdate, out AutoUpdateDownloadDescriptor updateAvailable)
		{
			updateAvailable = null;
			
			try
			{
				// create a manual web service proxy based on the url specified in the options
				Debug.WriteLine(string.Format("Creating a web service proxy to the following url.\n\tThe web service url is '{0}'.", options.WebServiceUrl), MY_TRACE_CATEGORY);			
				AutoUpdateWebServiceProxy service = new AutoUpdateWebServiceProxy(options.WebServiceUrl);

				// use the web service to query for updates
				Debug.WriteLine(string.Format("Querying the web service for the latest version of '{0}'.\n\tThe current product's version is '{1}'.\n\tThe current product's id is '{2}'.\n\tThe web service url is '{3}'.", productToUpdate.Name, productToUpdate.Version.ToString(), productToUpdate.Id, options.WebServiceUrl), MY_TRACE_CATEGORY);			
				XmlNode node = service.QueryLatestVersion(productToUpdate.Name, productToUpdate.Version.ToString(), productToUpdate.Id);
				
				// if the service returned no results, then there is no update availabe
				if (node == null)
				{
					// bail out 
					Debug.WriteLine(string.Format("No updates are available from the web service at '{0}' for this product.", options.WebServiceUrl), MY_TRACE_CATEGORY);
					return false;
				}

				// otherwise create a reader and try and read the xml from the xml node returned from the web service
				XmlAutoUpdateManifestReader reader = new XmlAutoUpdateManifestReader(node);

				// using the reader we can recreate the manifeset from the xml
				AutoUpdateManifest manifest = reader.Read();	

				/*
				* now create a download descriptor that says, yes we have found an update.
				* we are capable of downloading it, according to these options.
				* the autoupdate manager will decide which downloader to use to download the update
				* */
				updateAvailable = new AutoUpdateDownloadDescriptor(manifest, this, options);
				
				// just to let everyone know that there is a version available
				Debug.WriteLine(string.Format("Version '{0}' of '{1}' is available for download.\n\tThe download url is '{2}'.\n\tThe size of the download is {3}.", updateAvailable.Manifest.Product.Version.ToString(), updateAvailable.Manifest.Product.Name, updateAvailable.Manifest.UrlOfUpdate, this.FormatFileLengthForDisplay(updateAvailable.Manifest.SizeOfUpdate)), MY_TRACE_CATEGORY);

				// we've successfully queried for the latest version of the product to update
				return true;
			}
			catch(ThreadAbortException)
			{

			}
			catch (WebException ex)
			{
                Debug.WriteLine(ex.Message, MY_TRACE_CATEGORY);
			}
			return false;
		}
 /// <summary>
 /// Bubble sorts the elements in the descriptor array using their product verion (The newest version will be at element 0).
 /// </summary>
 /// <param name="updates"></param>
 /// <returns></returns>
 public static AutoUpdateDownloadDescriptor[] Sort(AutoUpdateDownloadDescriptor[] updates)
 {
     // front to back - 1
     for (int i = 0; i < updates.Length - 1; i++)
     {
         // front + 1 to back
         for (int j = i + 1; j < updates.Length; j++)
         {
             if (updates[i].Manifest.Product.Version < updates[j].Manifest.Product.Version)
             {
                 // swap i with j, where i=1 and j=2
                 AutoUpdateDownloadDescriptor update = updates[j];
                 updates[j] = updates[i];
                 updates[i] = update;
             }
         }
     }
     return(updates);
 }
        /// <summary>
        /// Adjusts the url where the .update can be found, using the product descriptor and the alternate download path 
        /// </summary>
        /// <remarks>
        /// By default the url probably points to some web url. When the update is copied to the alternate download path
        /// we want the download to occur from that path, so the url in the manifest must be manipulated to point the download
        /// to the update in the alternate path.
        /// </remarks>
        /// <param name="options"></param>
        /// <param name="downloadDescriptor"></param>
        public virtual void AdjustUrlOfUpdateInManifest(AutoUpdateOptions options, AutoUpdateDownloadDescriptor downloadDescriptor)
        {
            /*
             * we're supposed to be adjusting the the url where the update can be downloaded
             * to point to the alternate path
             * where ideally the manifest file will reside alongside the update
             * 
             * the problem is that the manifest file contains a url to where the update was originally downloaded
             * most likely some web server somewhere, which after the manifest is copied to some network file share
             * we won't want to use, more likely in an effort to keep the downloaders from going over the web
             * we'll try and tweak the url to just be the unc path of the download as it resides next to the 
             * manifest in the alternate download path
             * 
             * */

            try
            {

                // if there's no alternate path, don't worry about adjusting anything
                // as nothing is going to be copied anyways
                if (options.AlternatePath == null || options.AlternatePath == string.Empty)
                    // if there
                    return;

                // redirect the url of the update to the alternate location
                downloadDescriptor.Manifest.UrlOfUpdate = string.Format("{0}\\{1}\\{1}-{2}.Update", options.AlternatePath, downloadDescriptor.Manifest.Product.Name, downloadDescriptor.Manifest.Product.Version.ToString());			
            }
            catch(ThreadAbortException)
            {

            }
        }
        /// <summary>
        /// Creates a copy of the manifest file in the alternate path
        /// </summary>
        /// <param name="downloadDescriptor"></param>
        public virtual void CreateCopyOfManifestInAlternatePath(IProgressViewer progressViewer, AutoUpdateDownloadDescriptor downloadDescriptor)
        {
            try
            {
                // if the alternate path is not set, then we don't have to do this
                if (downloadDescriptor.Options.AlternatePath == null ||	downloadDescriptor.Options.AlternatePath == string.Empty)
                    return;

                // format a path to the product's alternate path
                string altPath = Path.Combine(downloadDescriptor.Options.AlternatePath, downloadDescriptor.Manifest.Product.Name);

                // if the path doesn't exist, just bail, we don't create alternate paths
                bool folderExists = Directory.Exists(altPath);
                Debug.WriteLine(string.Format("Confirming the product's 'Alternate Download Path' folder.\n\tThe folder '{0}' {1}.", altPath, (folderExists ? "already exists" : "does not exist")), MY_TRACE_CATEGORY);
                if (!folderExists)
                {
                    Debug.WriteLine(string.Format("Creating the product's 'Alternate Download Path' folder at '{0}'.", altPath), MY_TRACE_CATEGORY);
                    Directory.CreateDirectory(altPath);
                }
				
                // format a path to the file in the alternate path
                string dstPath = Path.Combine(altPath, string.Format("{0}-{1}.manifest", downloadDescriptor.Manifest.Product.Name, downloadDescriptor.Manifest.Product.Version.ToString()));

                bool fileExists = File.Exists(dstPath);
                Debug.WriteLine(string.Format("Preparing to copy the manifest to the product's 'Alternate Download Path' folder.\n\tThe file '{0}' {1}.", dstPath, (fileExists ? "already exists" : "does not exist")), MY_TRACE_CATEGORY);
							
                // otherwise write the manifest to the alternate path
                ProgressViewer.SetExtendedDescription(progressViewer, "Creating a backup copy of the manifest file.");
                Debug.WriteLine(string.Format("Copying the manifest to '{0}'.", dstPath), MY_TRACE_CATEGORY);
                XmlAutoUpdateManifestWriter.Write(downloadDescriptor.Manifest, dstPath, System.Text.Encoding.UTF8);				
            }
            catch(ThreadAbortException)
            {

            }
            catch(Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }
        /// <summary>
        /// Decrypts the .update file to a .zip file using the name of the .update file as a base in the same directory as the .update file
        /// </summary>
        /// <param name="progressViewer"></param>
        /// <param name="updateFilename"></param>
        /// <param name="zipFilename"></param>
        /// <returns></returns>
        protected virtual bool DecryptToZip(IProgressViewer progressViewer, AutoUpdateDownloadDescriptor downloadDescriptor, out string zipFilename)
        {
            zipFilename = null;
            try
            {						
                ProgressViewer.SetExtendedDescription(progressViewer, "Parsing update...");

                // save the path to the update
                string updateFilename = downloadDescriptor.DownloadedPath;

                // format the .zip file
                zipFilename = Path.Combine(Path.GetDirectoryName(updateFilename), Path.GetFileName(updateFilename).Replace(Path.GetExtension(updateFilename), null) + ".zip");
				
				/*
				 * Dev Note: Versions 1 & 2 encrypted the zip files. Version 3 in Carbon will not.
				 * Just copy the update to the zip location.
				 **/
				File.Copy(updateFilename, zipFilename);

				//// it is rijndael encrypted
				//RijndaelEncryptionEngine ee = new RijndaelEncryptionEngine();
								
				//// decrypt the .update file to a .zip file
				//Debug.WriteLine(string.Format("Converting the update into an archive.\n\tThe archive will exist at '{0}'.", zipFilename), MY_TRACE_CATEGORY);
				//ee.Decrypt(updateFilename, zipFilename);				
				
                return true;
            }
            catch(ThreadAbortException)
            {

            }
            return false;
        }
        /// <summary>
        /// Unzips the .zip file to a directory of it's own using the name of the .zip file as a base
        /// </summary>
        /// <param name="progressViewer"></param>
        /// <param name="zipFilename"></param>
        /// <returns></returns>
		protected virtual bool Unzip(IProgressViewer progressViewer, AutoUpdateDownloadDescriptor downloadDescriptor, string zipFilename)
		{
			ZipInputStream zipStream = null;
			FileStream fs = null;
			string newVersionPath = null;

			try
			{
				// calculate the rootname 
				//string rootName = Path.GetFileName(zipFilename).Replace(Path.GetExtension(zipFilename), null);

				//// the text to remove includes the name of the product and a dash
				//string prependedTextToRemove = string.Format("{0}-", downloadDescriptor.Manifest.Product.Name);

				//// remove that and we're left with a version
				//rootName = rootName.Replace(prependedTextToRemove, null);

				// extract here
				string rootPath = Path.GetDirectoryName(zipFilename);

				// the destination where the files will be unzipped for the new version
				//newVersionPath = Path.Combine(rootPath, rootName);
				newVersionPath = Path.Combine(rootPath, downloadDescriptor.Manifest.Product.Version.ToString());

				// make sure the directory where the new version will be extracted exists
				bool folderExists = Directory.Exists(newVersionPath);
				Debug.WriteLine(string.Format("Confirming the new version's path.\n\tThe folder '{0}' {1}.", newVersionPath, (folderExists ? "already exists" : "does not exist")), MY_TRACE_CATEGORY);
				if (!folderExists)
				{
					Debug.WriteLine(string.Format("Creating the new verion's folder '{0}'.", newVersionPath), MY_TRACE_CATEGORY);
					Directory.CreateDirectory(newVersionPath);
				}

				// try and find the postbuildevent.bat file
				string postBuildFile = Path.Combine(rootPath, "PostBuildEvent.bat");

				// open the zip file using a zip input stream
				Debug.WriteLine(string.Format("Opening the archive '{0}' for reading.", zipFilename), MY_TRACE_CATEGORY);
				zipStream = new ZipInputStream(File.OpenRead(zipFilename));

				// ready each zip entry
				ZipEntry zipEntry;
				while ((zipEntry = zipStream.GetNextEntry()) != null)
				{
					try
					{
						string zipEntryFilename = Path.Combine(rootPath, zipEntry.Name);
						zipEntryFilename = zipEntryFilename.Replace("/", "\\");

						// trace the entry to where it is going
						Debug.WriteLine(string.Format("Extracting '{0}' to '{1}'.", zipEntry.Name, zipEntryFilename), MY_TRACE_CATEGORY);

						if (zipEntry.IsDirectory)
						{
							Debug.WriteLine(string.Format("Creating the folder '{0}'.", zipEntryFilename), MY_TRACE_CATEGORY);
							Directory.CreateDirectory(zipEntryFilename);
						}
						else
						{
							ProgressViewer.SetExtendedDescription(progressViewer, "Extracting " + zipEntry.Name + "...");

							// make sure the directory exists
							FileInfo fi = new FileInfo(zipEntryFilename);
							DirectoryInfo di = fi.Directory;
							if (!Directory.Exists(di.FullName))
								Directory.CreateDirectory(di.FullName);
							fi = null;
							di = null;

							// create each file
							fs = File.Create(zipEntryFilename);
							int size = 2048;
							byte[] data = new byte[size];
							while (true)
							{
								size = zipStream.Read(data, 0, data.Length);
								if (size > 0)
									fs.Write(data, 0, size);
								else
									break;
							}
							// close the extracted file
							fs.Close();
							fs = null;
						}
					}
					catch (Exception ex)
					{
						Debug.WriteLine(ex);
					}
				}

				// close the zip stream
				zipStream.Close();

				RunFileIfFound(progressViewer, postBuildFile);

				return true;
			}
			catch (ThreadAbortException)
			{
				try
				{
					// make sure the streams are closed
					if (zipStream != null)
						zipStream.Close();

					if (fs != null)
						fs.Close();

					// delete the root folder of the new install upon cancellation
					Directory.Delete(newVersionPath, true);
				}
				catch (Exception ex)
				{
					Debug.WriteLine(ex);
				}
			}
			catch (Exception ex)
			{
				Debug.WriteLine(ex);
			}
			finally
			{
				// make sure the streams are closed
				if (zipStream != null)
					zipStream.Close();

				if (fs != null)
					fs.Close();
			}

			return false;
		}
        /// <summary>
        /// Sorts the available downloads and returns the newest download descriptor as the one that should be downloaded
        /// </summary>
        /// <param name="updates"></param>
        /// <returns></returns>
        protected virtual AutoUpdateDownloadDescriptor SelectTheDownloadWithTheNewestUpdate(AutoUpdateDownloadDescriptor[] downloadDescriptors)
        {
            try
            {
                // if there are no downloads
                if (downloadDescriptors == null)
                    // then simply say so
                    return null;

                if (downloadDescriptors.Length > 0)
                {
                    // otherwise, sort them into descending order with the newest version at index zero.
                    downloadDescriptors = AutoUpdateDownloadDescriptor.Sort(downloadDescriptors);
				
                    // simply return the first one
                    return downloadDescriptors[0];
                }
            }
            catch(ThreadAbortException)
            {

            }

            // otherwise don't
            return null;
        }		
        /// <summary>
        /// Installs the .update file specified by decrypting it and then unziping the contents to a new versioned directory (ie. 1.0.0.1)
        /// </summary>
        /// <param name="progressViewer"></param>
        /// <param name="updateFilename"></param>
        /// <returns></returns>
        protected virtual bool InstallUpdate(IProgressViewer progressViewer, AutoUpdateDownloadDescriptor downloadDescriptor)
        {
            string zipFilename = null;
            try
            {
                Debug.WriteLine(string.Format("Preparing to install update from '{0}'.", downloadDescriptor.DownloadedPath), MY_TRACE_CATEGORY);

                // decrypt the .update file first				
                if (!this.DecryptToZip(progressViewer, downloadDescriptor, out zipFilename))
                    return false;

                // then unzip the .zip file
                if (this.Unzip(progressViewer, downloadDescriptor, zipFilename))
                {	// delete the zip file
                    File.Delete(zipFilename);
                    return true;
                }
            }
            catch(ThreadAbortException)
            {
                try
                {
                    // delete the zip file
                    File.Delete(zipFilename);
                }
                catch(Exception ex)
                {
					Debug.WriteLine(ex);
                }
            }

            return false;
        }
		/// <summary>
		/// Initializes a new instance of the AutoUpdateDownloadDescriptorEventArgs class
		/// </summary>
		/// <param name="downloadDescriptor">The descriptor that describes the download.</param>
		public AutoUpdateDownloadDescriptorEventArgs(AutoUpdateDownloadDescriptor downloadDescriptor) 
			: base()
		{
			_descriptor = downloadDescriptor;
		}
		/// <summary>
		/// Initializes a new instance of the AutoUpdateManagerWithDownloadDescriptorCancelEventArgs class.
		/// </summary>
		/// <param name="manager">The AutoUpdateManager that is handling the update.</param>
		/// <param name="progressViewer">The IProgressViewer that can be used to display progress about the update.</param>
		/// <param name="downloadDescriptor">The AutoUpdateDownloadDescriptor that describes teh update available.</param>
		/// <param name="cancel">A flag that indicates whether the event should be cancelled or not.</param>
		public AutoUpdateManagerWithDownloadDescriptorCancelEventArgs(AutoUpdateManager manager, IProgressViewer progressViewer, AutoUpdateDownloadDescriptor downloadDescriptor, bool cancel)
			: base(manager, progressViewer, downloadDescriptor)
		{
			_cancel = cancel;
		}
 /// <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>
		/// 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);
        }
Beispiel #15
0
 /// <summary>
 /// Initializes a new instance of the AutoUpdateDownloadDescriptorCancelEventArgs class.
 /// </summary>
 /// <param name="cancel">A flag that indicates whether the event should be cancelled.</param>
 /// <param name="updateDescriptor">The AutoUpdateDownloadDescriptor that is the context of the event.</param>
 public AutoUpdateDownloadDescriptorCancelEventArgs(bool cancel, AutoUpdateDownloadDescriptor downloadDescriptor)
     : base(downloadDescriptor)
 {
     _cancel = cancel;
 }
		/// <summary>
		/// Bubble sorts the elements in the descriptor array using their product verion (The newest version will be at element 0).
		/// </summary>
		/// <param name="updates"></param>
		/// <returns></returns>
		public static AutoUpdateDownloadDescriptor[] Sort(AutoUpdateDownloadDescriptor[] updates)
		{
			// front to back - 1 
			for(int i = 0; i < updates.Length - 1; i++)
			{
				// front + 1 to back
				for(int j = i + 1; j < updates.Length; j++)
				{			
					if (updates[i].Manifest.Product.Version < updates[j].Manifest.Product.Version)
					{											 
						// swap i with j, where i=1 and j=2
						AutoUpdateDownloadDescriptor update = updates[j];
						updates[j] = updates[i];
						updates[i] = update;
					}													
				}
			}
			return updates;
		}
        /// <summary>
        /// Creates a copy of the update file in the alternate path
        /// </summary>
        /// <param name="progressViewer"></param>
        /// <param name="updateFilename"></param>
        /// <returns></returns>
        public virtual void CreateCopyOfUpdateInAlternatePath(IProgressViewer progressViewer, AutoUpdateDownloadDescriptor downloadDescriptor)
        {				 													
            try
            {
                // if the alternate path is not set, then we don't have to do this
                if (downloadDescriptor.Options.AlternatePath == null ||	downloadDescriptor.Options.AlternatePath == string.Empty)
                    return;

                // take the alternate path
                string altPath = Path.Combine(downloadDescriptor.Options.AlternatePath, downloadDescriptor.Manifest.Product.Name);

                // see if the folder exists
                bool folderExists = Directory.Exists(altPath);				
                Debug.WriteLine(string.Format("Confirming the product's 'Alternate Download Path' folder.\n\tThe folder '{0}' {1}.", altPath, (folderExists ? "already exists" : "does not exist")), MY_TRACE_CATEGORY);
                if (!folderExists)
                {
                    Debug.WriteLine(string.Format("Creating the product's 'Alternate Download Path' folder at '{0}'.", altPath), MY_TRACE_CATEGORY);
                    Directory.CreateDirectory(altPath);
                }
	
                // format the backup filename from the alternate path, and the url where the update
                string dstPath = Path.Combine(altPath, Path.GetFileName(downloadDescriptor.Manifest.UrlOfUpdate));

                // see if the file already exists
                bool fileExists = File.Exists(dstPath);
                Debug.WriteLine(string.Format("Preparing to copy the update to the product's 'Alternate Download Path' folder.\n\tThe file '{0}' {1}.", dstPath, (fileExists ? "already exists" : "does not exist")), MY_TRACE_CATEGORY);
				
                // copy the .update we downloaded to the backup location in the alternate path directory
                ProgressViewer.SetExtendedDescription(progressViewer, "Creating a backup copy of the update file.");
                Debug.WriteLine(string.Format("Copying the update to '{0}'.", dstPath), MY_TRACE_CATEGORY);				
                File.Copy(downloadDescriptor.DownloadedPath, dstPath, false);								
            }
            catch(ThreadAbortException)
            {

            }
            catch(Exception ex)
            {
                Debug.WriteLine(ex);
            }
        }		
		/// <summary>
		/// Initializes a new instance of the AutoUpdateDownloadDescriptorCancelEventArgs class.
		/// </summary>
		/// <param name="cancel">A flag that indicates whether the event should be cancelled.</param>
		/// <param name="updateDescriptor">The AutoUpdateDownloadDescriptor that is the context of the event.</param>
		public AutoUpdateDownloadDescriptorCancelEventArgs(bool cancel, AutoUpdateDownloadDescriptor downloadDescriptor) 
			: base(downloadDescriptor)
		{
			_cancel = cancel;
		}
		/// <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>
		/// Initializes a new instance of the AutoUpdateManagerWithDownloadDescriptorEventArgs class.
		/// </summary>
		/// <param name="manager">The AutoUpdateManager that is handling the update.</param>
		/// <param name="progressViewer">The IProgressViewer that can be used to display progress about the update.</param>
		/// <param name="downloadDescriptor">The AutoUpdateDownloadDescriptor that describes teh update available.</param>
		public AutoUpdateManagerWithDownloadDescriptorEventArgs(AutoUpdateManager manager, IProgressViewer progressViewer, AutoUpdateDownloadDescriptor downloadDescriptor)
			: base(manager, progressViewer)
		{
			_downloadDescriptor = downloadDescriptor;
		}
Beispiel #21
0
 /// <summary>
 /// Initializes a new instance of the AutoUpdateDownloadDescriptorEventArgs class
 /// </summary>
 /// <param name="downloadDescriptor">The descriptor that describes the download.</param>
 public AutoUpdateDownloadDescriptorEventArgs(AutoUpdateDownloadDescriptor downloadDescriptor)
     : base()
 {
     _descriptor = downloadDescriptor;
 }
		/// <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;			
		}