public static AutoUpdateProductDescriptor FromAssembly(Assembly assembly, Version version)
		{			
			// create a product descriptor
			AutoUpdateProductDescriptor pd = new AutoUpdateProductDescriptor();				
						
			// grab its assembly name
			AssemblyName assemblyName = assembly.GetName();

			// set the name of the product
			pd.Name = assemblyName.Name.Replace(".exe", null);
			
			// the version will be the starting folder name parsed to a version
			pd.Version = version;

			// create an assembly attribute reader
			AssemblyAttributeReader reader = new AssemblyAttributeReader(assembly);

			// set the product id
			ProductIdentifierAttribute pia = reader.GetProductIdentifierAttribute();
			if (pia != null)
				pd.Id = pia.Id;

			// set whether the exe requires registration
			RequiresRegistrationAttribute rra = reader.GetRequiresRegistrationAttribute();
			if (rra != null)
				pd.RequiresRegistration = rra.RequiresRegistration;
		
			return pd;			
		}
		/// <summary>
		/// Reads the meta data from assembly attributes and extracts the shell icon to display on the progress dialog
		/// </summary>
		/// <param name="assembly"></param>
		private void DisplayInformationAboutAssembly(System.Reflection.Assembly assembly, bool showVersion)
		{
			try
			{
				ProgressViewer.SetTitle(this, "Loading...");
				ProgressViewer.SetDescription(this, "This operation could take several seconds...");

				if (assembly != null)
				{
					// snag the name of the file minus path and extention and set it as the heading
					string filename = System.IO.Path.GetFileName(assembly.Location);
					filename = filename.Replace(System.IO.Path.GetExtension(assembly.Location), null);							
					ProgressViewer.SetHeading(this, filename);

					DirectoryInfo directory = new DirectoryInfo(Application.StartupPath);

//					// snag the version of the assembly, and tack it onto the heading
					AssemblyAttributeReader reader = new AssemblyAttributeReader(assembly);
//					Version v = reader.GetAssemblyVersion();
//					if (v != null)					
					ProgressViewer.SetHeading(this, filename + (showVersion ? " Version " + SnapInHostingEngine.Instance.AppVersion.ToString(): null));
									
					// snag the company that made the assembly, and set it in the title
					System.Reflection.AssemblyCompanyAttribute[] companyAttributes = reader.GetAssemblyCompanyAttributes();
					if (companyAttributes != null)
						if (companyAttributes.Length > 0)
							if (companyAttributes[0].Company != null && companyAttributes[0].Company != string.Empty)
                                ProgressViewer.SetTitle(this, companyAttributes[0].Company + " " + filename);

					// snag the image from the assembly, it should be an executable so...
					Icon largeIcon = ShellInformation.GetIconFromPath(assembly.Location, IconSizes.LargeIconSize, IconStyles.NormalIconStyle, FileAttributes.Normal);	
					if (largeIcon != null)							
						ProgressViewer.SetImage(this, largeIcon.ToBitmap() as Image);
				
					Icon smallIcon = ShellInformation.GetIconFromPath(assembly.Location, IconSizes.SmallIconSize, IconStyles.NormalIconStyle, FileAttributes.Normal);	
					if (smallIcon != null)				
						this.Icon = smallIcon;
				}
			}
			catch(System.Exception systemException)
			{
				System.Diagnostics.Trace.WriteLine(systemException);
			}
		}
		public void DiscoverTypesUsingMetaData(FileInfo fileInfo)
		{
			try
			{
				// try and load the file as a .net assembly
				Assembly assembly = Assembly.LoadFrom(fileInfo.FullName);				
				
				AssemblyAttributeReader r = new AssemblyAttributeReader(assembly);
				SnapInExportedFromAssemblyAttribute[] exports = r.GetExportedSnapInAttributes();
				foreach(SnapInExportedFromAssemblyAttribute attribute in exports)
				{
					Type t = attribute.Type;
					if (t != null)
						this.OnPublicClassDiscovered(this, new RuntimeClassProviderEventArgs(assembly, t));
				}

				assembly = null;
			}
			catch(BadImageFormatException)
			{
				// fileInfo.FullName is not a valid .NET assembly
			}
			catch(System.Exception systemException) 
			{
				System.Diagnostics.Trace.WriteLine(systemException); 
			}	
		}
		/// <summary>
		/// Reflect upon the starting executable and snag it's properties
		/// </summary>
		protected void MorphAttributesToReflectStartingExecutable()
		{
			try
			{
				Assembly assembly = SnapInHostingEngine.GetExecutingInstance().StartingExecutable;
				if (assembly != null)
				{
					// snag the name of the file minus path and extention and set it as the heading
					string filename = System.IO.Path.GetFileName(assembly.Location);
					filename = filename.Replace(System.IO.Path.GetExtension(assembly.Location), null);							
					
					AssemblyAttributeReader reader = new AssemblyAttributeReader(assembly);
									
					// snag the company that made the assembly, and set it in the title
					System.Reflection.AssemblyCompanyAttribute[] companyAttributes = reader.GetAssemblyCompanyAttributes();
					if (companyAttributes != null)
						if (companyAttributes.Length > 0)
							if (companyAttributes[0].Company != null && companyAttributes[0].Company != string.Empty)
								this.Text = filename; // companyAttributes[0].Company + " " + filename;

					// snag the image from the assembly, it should be an executable so...
					Icon icon = ShellInformation.GetIconFromPath(assembly.Location,	IconSizes.SmallIconSize, IconStyles.NormalIconStyle, FileAttributes.Normal);	
					if (icon != null)
						this.Icon = icon;
				}
			}
			catch(System.Exception systemException)
			{
				System.Diagnostics.Trace.WriteLine(systemException);
			}
		}