Пример #1
0
        /// <summary>
        /// Initialize
        /// </summary>
        public static void Initialize()
        {
            var isFullTrust = WebHelper.GetTrustLevel() == AspNetHostingPermissionLevel.Unrestricted;

            if (!isFullTrust)
            {
                throw new ApplicationException("SmartStore.NET requires Full Trust mode. Please enable Full Trust for your web site or contact your hosting provider.");
            }

            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/x64)
            // ensures that unmanaged native dependencies can be resolved successfully.
            SetNativeDllPath();
            //SetPrivateEnvPath();

            DynamicModuleUtility.RegisterModule(typeof(AutofacRequestLifetimeHttpModule));

            #region Plugins

            var incompatiblePlugins = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            using (Locker.GetWriteLock())
            {
                _shadowCopyDir = new DirectoryInfo(AppDomain.CurrentDomain.DynamicDirectory);

                var plugins           = LoadPluginDescriptors().ToArray();
                var compatiblePlugins = plugins.Where(x => !x.Incompatible).ToArray();

                // If plugins state is dirty, we copy files over to the dynamic folder,
                // otherwise we just reference the previously copied file.
                var dirty = DetectAndCleanStalePlugins(compatiblePlugins);

                foreach (var plugin in plugins)
                {
                    if (plugin.Incompatible)
                    {
                        incompatiblePlugins.Add(plugin.SystemName);
                        continue;
                    }
                    else
                    {
                        _referencedPlugins[plugin.SystemName] = plugin;
                    }

                    try
                    {
                        // Shadow copy main plugin assembly
                        plugin.ReferencedAssembly = Probe(plugin.OriginalAssemblyFile, dirty);

                        // Shadow copy other referenced plugin local assemblies
                        if (plugin.ReferencedLocalAssemblyFiles != null)
                        {
                            foreach (var assemblyFile in plugin.ReferencedLocalAssemblyFiles)
                            {
                                Probe(assemblyFile, dirty);
                            }
                        }

                        if (!plugin.Installed)
                        {
                            _inactiveAssemblies.Add(plugin.ReferencedAssembly);
                        }

                        // Initialize: Find IPlugin, IPreApplicationStart, IConfigurable etc.
                        ActivatePlugin(plugin);
                    }
                    catch (UnauthorizedAccessException)
                    {
                        // Throw the exception if its UnauthorizedAccessException as this will
                        // be because we most likely cannot copy to the dynamic folder.
                        throw;
                    }
                    catch (ReflectionTypeLoadException ex)
                    {
                        var msg = string.Empty;
                        foreach (var e in ex.LoaderExceptions)
                        {
                            msg += e.Message + Environment.NewLine;
                        }

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

                        HandlePluginActivationException(ex, plugin, msg, incompatiblePlugins);
                    }
                }

                if (dirty)
                {
                    // Save current hash of all deployed plugins to disk
                    var hash = ComputePluginsHash(_referencedPlugins.Values.OrderBy(x => x.FolderName).ToArray());
                    SavePluginsHash(hash);

                    // Save names of all deployed assemblies to disk (so we can nuke them later)
                    SavePluginsAssemblies(_referencedPlugins.Values);
                }

                IncompatiblePlugins = incompatiblePlugins.AsReadOnly();
            }

            #endregion
        }
Пример #2
0
        private static void InitializeCore()
        {
            var isFullTrust = WebHelper.GetTrustLevel() == AspNetHostingPermissionLevel.Unrestricted;

            if (!isFullTrust)
            {
                throw new ApplicationException("Smartstore requires Full Trust mode. Please enable Full Trust for your web site or contact your hosting provider.");
            }

            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/x64)
            // ensures that unmanaged native dependencies can be resolved successfully.
            SetNativeDllPath();

            DynamicModuleUtility.RegisterModule(typeof(AutofacRequestLifetimeHttpModule));

            var incompatiblePlugins = (new HashSet <string>(StringComparer.OrdinalIgnoreCase)).AsSynchronized();
            var inactiveAssemblies  = _inactiveAssemblies.AsSynchronized();
            var dirty = false;

            var watch = Stopwatch.StartNew();

            _shadowCopyDir = new DirectoryInfo(AppDomain.CurrentDomain.DynamicDirectory);

            var plugins           = LoadPluginDescriptors().ToArray();
            var compatiblePlugins = plugins.Where(x => !x.Incompatible).ToArray();
            var hasher            = new PluginsHasher(compatiblePlugins);

            Logger.DebugFormat("Loaded plugin descriptors. {0} total, {1} incompatible.", plugins.Length, plugins.Length - compatiblePlugins.Length);

            var ms = watch.ElapsedMilliseconds;

            Logger.DebugFormat("INIT PLUGINS (LoadPluginDescriptors). Time elapsed: {0} ms.", ms);

            // If plugins state is dirty, we copy files over to the dynamic folder,
            // otherwise we just reference the previously copied file.
            dirty = DetectAndCleanStalePlugins(compatiblePlugins, hasher);

            // Perf: Initialize/probe all plugins in parallel
            plugins.AsParallel().ForAll(x =>
            {
                // Deploy to ASP.NET dynamic folder.
                DeployPlugin(x, dirty);

                // Finalize
                FinalizePlugin(x);
            });

            //// Retry when failed, because during parallel execution assembly loading MAY fail.
            //// Therefore we retry initialization for failed plugins, but sequentially this time.
            //foreach (var p in plugins)
            //{
            //	// INFO: this seems redundant, but it's ok:
            //	// DeployPlugin() only probes assemblies that are not loaded yet.
            //	DeployPlugin(p, dirty);

            //	// Finalize
            //	FinalizePlugin(p);
            //}

            if (dirty && DataSettings.DatabaseIsInstalled())
            {
                // Save current hash of all deployed plugins to disk
                hasher.Persist();

                // Save names of all deployed assemblies to disk (so we can nuke them later)
                SavePluginsAssemblies(_referencedPlugins.Values);
            }

            IncompatiblePlugins = incompatiblePlugins.AsReadOnly();

            ms = watch.ElapsedMilliseconds;
            Logger.DebugFormat("INIT PLUGINS (Deployment complete). Time elapsed: {0} ms.", ms);

            void DeployPlugin(PluginDescriptor p, bool shadowCopy)
            {
                if (p.Incompatible)
                {
                    // Do nothing if plugin is incompatible
                    return;
                }

                // First copy referenced local assemblies (if any)
                for (int i = 0; i < p.ReferencedLocalAssemblies.Length; ++i)
                {
                    var refAr = p.ReferencedLocalAssemblies[i];
                    if (refAr.Assembly == null)
                    {
                        Probe(refAr, p, shadowCopy);
                    }
                }

                // Then copy main plugin assembly
                var ar = p.Assembly;

                if (ar.Assembly == null)
                {
                    Probe(ar, p, shadowCopy);
                    if (ar.Assembly != null)
                    {
                        // Activate (even if uninstalled): Find IPlugin, IPreApplicationStart, IConfigurable etc.
                        ActivatePlugin(p);
                    }
                }
            }

            void FinalizePlugin(PluginDescriptor p)
            {
                _referencedPlugins[p.SystemName] = p;

                if (p.Incompatible)
                {
                    incompatiblePlugins.Add(p.SystemName);
                    return;
                }

                var firstFailedAssembly = p.ReferencedLocalAssemblies.FirstOrDefault(x => x.ActivationException != null);

                if (firstFailedAssembly == null && p.Assembly.ActivationException != null)
                {
                    firstFailedAssembly = p.Assembly;
                }
                if (firstFailedAssembly != null)
                {
                    Logger.ErrorFormat("Assembly probing failed for '{0}': {1}", firstFailedAssembly.File.Name, firstFailedAssembly.ActivationException.Message);
                    p.Incompatible = true;
                    incompatiblePlugins.Add(p.SystemName);
                }

                if ((!p.Installed || firstFailedAssembly != null) && p.Assembly.Assembly != null)
                {
                    inactiveAssemblies.Add(p.Assembly.Assembly);
                }
            }
        }
Пример #3
0
        /// <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();
            }
        }