/// <summary>
		/// Uses the PluginProviders specified to load Plugin Types that will be used to create Plugins.
		/// </summary>
		/// <param name="progressViewer">The callback object implementing IProgressViewer that will be used to monitor progress.</param>
		/// <param name="pluginProviders">The collection of PluginProviders that will be used to load the Plugin Types from their various sources.</param>
		/// <returns></returns>
		public static TypeCollection LoadPluginTypes(IProgressViewer progressViewer, PluginProviderCollection pluginProviders)
		{
			TypeCollection pluginTypes = new TypeCollection();
			foreach (PluginProvider provider in pluginProviders)
			{
				try
				{
					Log.WriteLine("Loading Plugin Types. PluginProvider: '{0}'.", provider.Name);

					TypeCollection types = provider.LoadPluginTypes(progressViewer);
					if (types != null)
					{
						pluginTypes.AddRange(types);
					}
				}
				catch(Exception ex)
				{
					Log.WriteLine(ex);
				}
			}
			return pluginTypes;
		}
		public void Run(Assembly startingAssembly, string[] args)
		{
			this.AssertThisIsTheOnlyRunningContext();

			// create a new application context
			_appContext = new PluginApplicationContext();	

			// save the command line args
			_commandLineArgs = args;

			if (CarbonConfig.SingleInstance)
			{
				// create a new instance manager, don't dispose of it just yet as we'll need to have our ui plugin 
				// grab it and listen for events until the plugin context is destroyed...
				_instanceManager = new InstanceManager(CarbonConfig.SingleInstancePort, CarbonConfig.SingleInstanceMutexName);

				// check to see if this one is the only instance running
				if (!_instanceManager.IsOnlyInstance)
				{						
					// if not, forward our command line, and then instruct the 
					_instanceManager.SendCommandLineToPreviousInstance(PluginContext.Current.CommandLineArgs);
					return;
				}
			}
							
			// load the Carbon core sub-system providers 
			_windowProviders = CarbonConfig.GetWindowProviders();
			_configurationProviders = CarbonConfig.GetConfigurationProviders();
			//_encryptionProviders = CarbonConfig.GetEncryptionProviders();
			_pluginProviders = CarbonConfig.GetPluginProviders();
			
			// show the splash _splashWindow if the config specifies			
			if (CarbonConfig.ShowSplashWindow)
			{										
				/*
				 * Not-Threaded
				 * */
				using (WindowProvider splashWindowProvider = this.GetSplashWindowProvider())
				{
				    _splashWindow = splashWindowProvider.CreateWindow(null);
				}		
				
				_splashWindow.Show();
				_splashWindow.Refresh();				
				_progressViewer = _splashWindow as IProgressViewer;
			}

			ProgressViewer.SetExtendedDescription(_progressViewer, "Initializing Carbon Framework System Providers.");

			// start configuration providers
			ConfigurationProvidersManager.InstructConfigurationProvidersToLoad(_progressViewer, _configurationProviders);

			// use the plugin manager to load the plugin types that the plugin providers want loaded
			using (TypeCollection pluginTypes = PluginManager.LoadPluginTypes(_progressViewer, _pluginProviders))
			{
				// use the plugin manager to create descriptors for all of the plugins
				using (_pluginDescriptors = PluginManager.CreatePluginDescriptors(_progressViewer, pluginTypes))
				{
					// validate the plugin dependencies
					PluginManager.ValidatePluginDependencies(_progressViewer, _pluginDescriptors);

					// sort plugins to have the least dependent plugins first
					// NOTE: Always sort first because the dependencies are taken into account during instance construction!
					_pluginDescriptors = PluginManager.Sort(_pluginDescriptors, true);

					// create the plugins
					PluginManager.CreatePluginInstances(_progressViewer, _pluginDescriptors);

					// start plugins
					PluginManager.StartPlugins(_progressViewer, _pluginDescriptors);
			
					// if we are supposed to run a message loop, do it now
					if (CarbonConfig.RunApplicationContext)
					{
						this.OnEnteringMainMessageLoop(new PluginContextEventArgs(this));
						
						// run the plugin context's main message loop
						Application.Run(this.ApplicationContext);
						
						this.OnExitingMainMessageLoop(new PluginContextEventArgs(this));
					}

					// sort plugins to have the most dependent plugins first
					_pluginDescriptors = PluginManager.Sort(_pluginDescriptors, false);

					// stop plugins
					PluginManager.StopPlugins(null, _pluginDescriptors);
				}
			}

			// stop configuration providers
			// start configuration providers
			ConfigurationProvidersManager.InstructConfigurationProvidersToSave(_configurationProviders);			
		}
		/// <summary>
		/// Cleanup any managed resources
		/// </summary>
		protected override void DisposeOfManagedResources()
		{			
			base.DisposeOfManagedResources ();

			if (_configurationProviders != null)
			{
				_configurationProviders.Dispose();
				_configurationProviders = null;
			}

			//if (_encryptionProviders != null)
			//{
			//    _encryptionProviders.Dispose();
			//    _encryptionProviders = null;
			//}

			if (_pluginProviders != null)
			{
				_pluginProviders.Dispose();
				_pluginProviders = null;
			}

			if (_windowProviders != null)
			{
				_windowProviders.Dispose();
				_windowProviders = null;
			}

			if (_pluginDescriptors != null)
			{
				_pluginDescriptors.Dispose();
				_pluginDescriptors = null;
			}
			
			if (_instanceManager != null)
			{
				_instanceManager.Dispose();
				_instanceManager = null;
			}

			if (_gcTimer != null)
			{
				_gcTimer.Dispose();
				_gcTimer = null;
			}

			_commandLineArgs = null;
			_progressViewer = null;
		}