예제 #1
0
        /// <summary>
        /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan
        /// and excluding the ones passed in and excluding the exclusion list filter, the results of this are
        /// cached for performance reasons.
        /// </summary>
        /// <param name="excludeFromResults">
        /// An <see cref="IEnumerable{Assembly}"/> to exclude.
        /// </param>
        /// <returns>The collection of local assemblies.</returns>
        internal static HashSet <Assembly> GetAssembliesWithKnownExclusions(
            IEnumerable <Assembly> excludeFromResults = null)
        {
            using (var locker = new UpgradeableReadLock(LocalFilteredAssemblyCacheLocker))
            {
                if (LocalFilteredAssemblyCache.Any())
                {
                    return(LocalFilteredAssemblyCache);
                }

                locker.UpgradeToWriteLock();

                var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter);
                foreach (var assembly in assemblies)
                {
                    LocalFilteredAssemblyCache.Add(assembly);
                }

                return(LocalFilteredAssemblyCache);
            }
        }
예제 #2
0
        /// <summary>
        /// Lazily loads a reference to all assemblies and only local assemblies.
        /// This is a modified version of:
        /// <see href="http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder"/>
        /// </summary>
        /// <remarks>
        /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been
        /// loaded in the CLR, not all assemblies.
        /// See these threads:
        /// <see href="http://issues.umbraco.org/issue/U5-198"/>
        /// <see href="http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app"/>
        /// <see href="http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl"/>
        /// </remarks>
        /// <returns>
        /// The <see cref="HashSet{Assembly}"/>.
        /// </returns>
        internal static HashSet <Assembly> GetAllAssemblies()
        {
            using (var locker = new UpgradeableReadLock(Locker))
            {
                if (_allAssemblies == null)
                {
                    locker.UpgradeToWriteLock();

                    try
                    {
                        // NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have
                        // already been loaded in to the app domain, instead we will look directly into the bin folder and load each one.
                        var binFolder        = IOHelper.GetRootDirectoryBinFolder();
                        var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList();
                        var assemblies       = new HashSet <Assembly>();

                        foreach (var file in binAssemblyFiles)
                        {
                            try
                            {
                                var assemblyName = AssemblyName.GetAssemblyName(file);
                                assemblies.Add(Assembly.Load(assemblyName));
                            }
                            catch (Exception ex)
                            {
                                if (ex is SecurityException || ex is BadImageFormatException || ex is IOException)
                                {
                                    // Swallow exception but allow debugging.
                                    Debug.WriteLine(ex.Message);
                                }
                                else
                                {
                                    throw;
                                }
                            }
                        }

                        // If for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies.
                        if (!assemblies.Any())
                        {
                            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
                            {
                                assemblies.Add(assembly);
                            }
                        }

                        // Here we are trying to get the App_Code assembly
                        string[] fileExtensions = { ".cs", ".vb" };
                        var      appCodeFolder  = new DirectoryInfo(IOHelper.MapPath("~/App_code"));

                        // Check if the folder exists and if there are any files in it with the supported file extensions
                        if (appCodeFolder.Exists && fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))
                        {
                            var appCodeAssembly = Assembly.Load("App_Code");
                            if (!assemblies.Contains(appCodeAssembly))
                            {
                                assemblies.Add(appCodeAssembly);
                            }
                        }

                        // Now set the allAssemblies
                        _allAssemblies = new HashSet <Assembly>(assemblies);
                    }
                    catch (InvalidOperationException e)
                    {
                        if (!(e.InnerException is SecurityException))
                        {
                            throw;
                        }

                        _binFolderAssemblies = _allAssemblies;
                    }
                }

                return(_allAssemblies);
            }
        }