/// <summary>
        /// 获取描述文件
        /// </summary>
        /// <param name="pluginFolder">插件文件夹</param>
        /// <returns>原始和解析的描述文件</returns>
        private static IEnumerable <KeyValuePair <FileInfo, PluginDescriptor> > GetDescriptionFilesAndDescriptors(DirectoryInfo pluginFolder)
        {
            if (pluginFolder == null)
            {
                throw new ArgumentNullException("pluginFolder");
            }

            //create list (<file info, parsed plugin descritor>)
            var result = new List <KeyValuePair <FileInfo, PluginDescriptor> >();

            //add display order and path to list
            foreach (var descriptionFile in pluginFolder.GetFiles("Description.txt", SearchOption.AllDirectories))
            {
                if (!IsPackagePluginFolder(descriptionFile.Directory))
                {
                    continue;
                }

                //parse file
                var pluginDescriptor = PluginFileParser.ParsePluginDescriptionFile(descriptionFile.FullName);

                //populate list
                result.Add(new KeyValuePair <FileInfo, PluginDescriptor>(descriptionFile, pluginDescriptor));
            }

            //sort list by display order. NOTE: Lowest DisplayOrder will be first i.e 0 , 1, 1, 1, 5, 10
            //it's required: http://www.nopcommerce.com/boards/t/17455/load-plugins-based-on-their-displayorder-on-startup.aspx
            result.Sort((firstPair, nextPair) => firstPair.Value.DisplayOrder.CompareTo(nextPair.Value.DisplayOrder));
            return(result);
        }
Exemple #2
0
        /// <summary>
        /// Initialize
        /// </summary>
        public static void Initialize()
        {
            using (new WriteLockDisposable(Locker))
            {
                // TODO: Add verbose exception handling / raising here since this is happening on app startup and could
                // prevent app from starting altogether
                var pluginFolder = new DirectoryInfo(HostingEnvironment.MapPath(_pluginsPath));
                _shadowCopyFolder = new DirectoryInfo(HostingEnvironment.MapPath(_shadowCopyPath));

                var referencedPlugins = new List <PluginDescriptor>();

                _clearShadowDirectoryOnStartup = !String.IsNullOrEmpty(ConfigurationManager.AppSettings["ClearPluginsShadowDirectoryOnStartup"]) &&
                                                 Convert.ToBoolean(ConfigurationManager.AppSettings["ClearPluginsShadowDirectoryOnStartup"]);

                try
                {
                    var installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile(GetInstalledPluginsFilePath());

                    Debug.WriteLine("Creating shadow copy folder and querying for dlls");
                    //ensure folders are created
                    Directory.CreateDirectory(pluginFolder.FullName);
                    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);
                            }
                        }
                    }

                    //load description files
                    foreach (var descriptionFile in pluginFolder.GetFiles("Description.txt", SearchOption.AllDirectories))
                    {
                        try
                        {
                            //parse file
                            var description = PluginFileParser.ParsePluginDescriptionFile(descriptionFile.FullName);

                            //ensure that version of plugin is valid
                            if (!description.SupportedVersions.Contains(NopVersion.CurrentVersion, StringComparer.InvariantCultureIgnoreCase))
                            {
                                continue;
                            }

                            //some validation
                            if (String.IsNullOrWhiteSpace(description.SystemName))
                            {
                                throw new Exception(string.Format("A plugin '{0}' has no system name. Try assigning the plugin a unique name and recompiling.", descriptionFile.FullName));
                            }
                            if (referencedPlugins.Contains(description))
                            {
                                throw new Exception(string.Format("A plugin with '{0}' system name is already defined", description.SystemName));
                            }

                            //set 'Installed' property
                            description.Installed = installedPluginSystemNames
                                                    .ToList()
                                                    .Where(x => x.Equals(description.SystemName, StringComparison.InvariantCultureIgnoreCase))
                                                    .FirstOrDefault() != null;

                            //get list of all DLLs in plugins (not in bin!)
                            var pluginFiles = descriptionFile.Directory.GetFiles("*.dll", SearchOption.AllDirectories)
                                              //just make sure we're not registering shadow copied plugins
                                              .Where(x => !binFiles.Select(q => q.FullName).Contains(x.FullName))
                                              .Where(x => IsPackagePluginFolder(x.Directory))
                                              .ToList();

                            //other plugin description info
                            var mainPluginFile = pluginFiles.Where(x => x.Name.Equals(description.PluginFileName, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
                            description.OriginalAssemblyFile = mainPluginFile;

                            //shadow copy main pugin file
                            description.ReferencedAssembly = PerformFileDeploy(mainPluginFile);

                            //load all other referenced assemblies now
                            foreach (var plugin in pluginFiles
                                     .Where(x => !x.Name.Equals(mainPluginFile.Name, StringComparison.InvariantCultureIgnoreCase))
                                     .Where(x => !IsAlreadyLoaded(x)))
                            {
                                PerformFileDeploy(plugin);
                            }


                            //init plugin type (only one plugin per assembly is allowed)
                            foreach (var t in description.ReferencedAssembly.GetTypes())
                            {
                                if (typeof(IPlugin).IsAssignableFrom(t))
                                {
                                    if (!t.IsInterface)
                                    {
                                        if (t.IsClass && !t.IsAbstract)
                                        {
                                            description.PluginType = t;
                                            break;
                                        }
                                    }
                                }
                            }

                            referencedPlugins.Add(description);
                        }
                        catch (ReflectionTypeLoadException ex)
                        {
                            var msg = string.Empty;
                            foreach (var e in ex.LoaderExceptions)
                            {
                                msg += e.Message + Environment.NewLine;
                            }

                            msg += descriptionFile.DirectoryName + Environment.NewLine;

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

                            throw fail;
                        }
                        //catch (Exception ex)
                        //{
                        //    var fail = new Exception("Could not initialise plugin folder", ex);
                        //    Debug.WriteLine(fail.Message);
                        //    throw fail;
                        //}
                    }
                }
                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;
                }


                ReferencedPlugins = referencedPlugins;
            }
        }