/// <summary>
        /// Initialize
        /// </summary>
        public static void Initialize()
        {
			using (var updater = new AppUpdater())
			{
				// update from NuGet package, if it exists and is valid
				if (updater.TryUpdateFromPackage())
				{
					// [...]
				}

				// execute migrations
				updater.ExecuteMigrations();
			}
			
			// adding a process-specific environment path (either bin/x86 or bin/amd64)
			// ensures that unmanaged native dependencies can be resolved successfully.
			SetPrivateEnvPath();
			
			DynamicModuleUtility.RegisterModule(typeof(AutofacRequestLifetimeHttpModule));
			
			using (Locker.GetWriteLock())
            {
                // TODO: Add verbose exception handling / raising here since this is happening on app startup and could
                // prevent app from starting altogether
                var pluginFolderPath = CommonHelper.MapPath(_pluginsPath);
				_shadowCopyFolder = new DirectoryInfo(CommonHelper.MapPath(_shadowCopyPath));

                var incompatiblePlugins = new List<string>();
				_clearShadowDirectoryOnStartup = CommonHelper.GetAppSetting<bool>("sm:ClearPluginsShadowDirectoryOnStartup", true);
                try
                {	
                    Debug.WriteLine("Creating shadow copy folder and querying for dlls");
                    //ensure folders are created
                    Directory.CreateDirectory(pluginFolderPath);
                    Directory.CreateDirectory(_shadowCopyFolder.FullName);

                    // get list of all files in bin
                    var binFiles = _shadowCopyFolder.GetFiles("*", SearchOption.AllDirectories);
                    if (_clearShadowDirectoryOnStartup)
                    {
                        // clear out shadow copied plugins
                        foreach (var f in binFiles)
                        {
                            Debug.WriteLine("Deleting " + f.Name);
                            try
                            {
                                File.Delete(f.FullName);
                            }
                            catch (Exception exc)
                            {
                                Debug.WriteLine("Error deleting file " + f.Name + ". Exception: " + exc);
                            }
                        }
                    }

					// determine all plugin folders
					var pluginPaths = from x in Directory.EnumerateDirectories(pluginFolderPath)
									  where !x.IsMatch("bin") && !x.IsMatch("_Backup")
									  select Path.Combine(pluginFolderPath, x);

					var installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile();
					
					// now activate all plugins
					foreach (var pluginPath in pluginPaths)
					{
						var result = LoadPluginFromFolder(pluginPath, installedPluginSystemNames);
						if (result != null)
						{
							if (result.IsIncompatible)
							{
								incompatiblePlugins.Add(result.Descriptor.SystemName);
							}
							else if (result.Success)
							{
								_referencedPlugins[result.Descriptor.SystemName] = result.Descriptor;
							}
						}
					}

                }
                catch (Exception ex)
                {
                    var msg = string.Empty;
					for (var e = ex; e != null; e = e.InnerException)
					{
						msg += e.Message + Environment.NewLine;
					}

                    var fail = new Exception(msg, ex);
                    Debug.WriteLine(fail.Message, fail);

                    throw fail;
                }

                IncompatiblePlugins = incompatiblePlugins.AsReadOnly();

            }
        }
		private bool InstallablePackageExists()
		{
			using (var updater = new AppUpdater())
			{
				return updater.InstallablePackageExists();
			}
		}