Beispiel #1
0
        static TypeManager()
        {
            string assemblyLocation;
            var    isBundled = BundleHelper.InitializeBundledAssemblies();

            Instance = new TypeManager(isBundled);
            if (isBundled)
            {
                foreach (var name in BundleHelper.GetBundledAssembliesNames())
                {
                    Instance.ScanFile(name, bundled: true);
                }

                // in case of a bundled version `Assembly.GetExecutingAssembly().Location` returns an empty string
                assemblyLocation = Directory.GetCurrentDirectory();
            }
            else
            {
                assemblyLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            }
            Instance.Scan(assemblyLocation);
        }
Beispiel #2
0
        private TypeDefinition ResolveInner(TypeReference tp)
        {
            if (isBundled)
            {
                try
                {
                    var scope   = tp.GetElementType().Scope.ToString();
                    var bundled = BundleHelper.GetBundledAssemblyByFullName(scope);
                    if (bundled != null)
                    {
                        if (tp.IsArray)
                        {
                            // this supports only one-dimensional arrays for now
                            var elementType = bundled.MainModule.GetType(tp.Namespace, tp.GetElementType().Name);
                            return(new ArrayType(elementType).Resolve());
                        }

                        return(bundled.MainModule.GetType(tp.Namespace, tp.Name));
                    }
                }
                catch
                {
                    // intentionally do nothing, we'll try to resolve it later
                }
            }

            try
            {
                return(tp.Resolve());
            }
            catch
            {
                // we couldn't resolve it in any way, just give up
                return(null);
            }
        }
Beispiel #3
0
        private bool AnalyzeAssembly(string path, bool abortOnDuplicatedAssembly = false, bool bundled = false)
        {
            Logger.LogAs(this, LogLevel.Noisy, "Analyzing assembly {0}.", path);
            if (assemblyFromAssemblyName.Values.Any(x => x.Path == path))
            {
                Logger.LogAs(this, LogLevel.Warning, "Assembly {0} was already analyzed.", path);
                return(true);
            }
            AssemblyDefinition assembly;

            try
            {
                assembly = (bundled)
                    ? BundleHelper.GetBundledAssemblyByName(path)
                    : AssemblyDefinition.ReadAssembly(path);
            }
            catch (DirectoryNotFoundException)
            {
                Logger.LogAs(this, LogLevel.Warning, "Could not find file {0} to analyze.", path);
                return(false);
            }
            catch (FileNotFoundException)
            {
                Logger.LogAs(this, LogLevel.Warning, "Could not find file {0} to analyze.", path);
                return(false);
            }
            catch (BadImageFormatException)
            {
                // we hush this log because it is issued in binary Windows packages - we look for DLL files, but we
                // also bundle libgcc etc.
                Logger.LogAs(this, LogLevel.Noisy, "File {0} could not be analyzed due to invalid format.", path);
                return(false);
            }
            var assemblyName = assembly.FullName;

            if (!assemblyFromAssemblyName.ContainsKey(assemblyName))
            {
                assemblyFromAssemblyName.Add(assemblyName, GetAssemblyDescription(assemblyName, path));
            }
            else
            {
                if (path == assemblyFromAssemblyName[assemblyName].Path)
                {
                    return(true);
                }
                var description = assemblyFromAssemblyName[assemblyName];
                Logger.LogAs(this, LogLevel.Warning, "Assembly {0} is hidden by one located in {1} (same simple name {2}).",
                             path, description.Path, assemblyName);
            }
            var types = new List <TypeDefinition>();

            foreach (var module in assembly.Modules)
            {
                // we add the assembly's directory to the resolve directory - also all known directories
                knownDirectories.Add(Path.GetDirectoryName(path));
                var defaultAssemblyResolver = ((DefaultAssemblyResolver)module.AssemblyResolver);
                foreach (var directory in knownDirectories)
                {
                    defaultAssemblyResolver.AddSearchDirectory(directory);
                }
                foreach (var type in module.GetTypes())
                {
                    types.Add(type);
                }
            }

            var hidePluginsFromThisAssembly = false;

            // It happens that `entryAssembly` is null, e.g., when running tests inside MD.
            // In such case we don't care about hiding plugins, so we just skip this mechanism (as this is the simples solution to the NRE problem).
            var entryAssembly = Assembly.GetEntryAssembly();

            if (entryAssembly != null && IsReferenced(entryAssembly, assembly.FullName))
            {
                Logger.LogAs(this, LogLevel.Noisy, "Plugins from this assembly {0} will be hidden as it is explicitly referenced.", assembly.FullName);
                hidePluginsFromThisAssembly = true;
            }

            foreach (var type in types)
            {
                if (type.Interfaces.Any(i => ResolveInner(i)?.GetFullNameOfMember() == typeof(IPeripheral).FullName))
                {
                    Logger.LogAs(this, LogLevel.Noisy, "Peripheral type {0} found.", type.Resolve().GetFullNameOfMember());
                    foundPeripherals.Add(type);
                }

                if (type.CustomAttributes.Any(x => ResolveInner(x.AttributeType)?.GetFullNameOfMember() == typeof(PluginAttribute).FullName))
                {
                    Logger.LogAs(this, LogLevel.Noisy, "Plugin type {0} found.", type.Resolve().GetFullNameOfMember());
                    try
                    {
                        foundPlugins.Add(new PluginDescriptor(type, hidePluginsFromThisAssembly));
                    }
                    catch (Exception e)
                    {
                        //This may happend due to, e.g., version parsing error. The plugin is ignored.
                        Logger.LogAs(this, LogLevel.Error, "Plugin type {0} loading error: {1}.", type.GetFullNameOfMember(), e.Message);
                    }
                }

                if (IsAutoLoadType(type))
                {
                    var loadedType = GetTypeWithLazyLoad(type.GetFullNameOfMember(), assembly.FullName, path);
                    lock (autoLoadedTypeLocker)
                    {
                        autoLoadedTypes.Add(loadedType);
                    }
                    var autoLoadedType = autoLoadedTypeEvent;
                    if (autoLoadedType != null)
                    {
                        autoLoadedType(loadedType);
                    }
                    continue;
                }
                if (!ExtractExtensionMethods(type) && !IsInterestingType(type))
                {
                    continue;
                }
                // type is interesting, we'll put it into our dictionaries
                // after conflicts checking
                var fullName = type.GetFullNameOfMember();
                var newAssemblyDescription = GetAssemblyDescription(assembly.FullName, path);
                Logger.LogAs(this, LogLevel.Noisy, "Type {0} added.", fullName);
                if (assembliesFromTypeName.ContainsKey(fullName))
                {
                    assembliesFromTypeName[fullName].Add(newAssemblyDescription);
                    continue;
                }
                if (assemblyFromTypeName.ContainsKey(fullName))
                {
                    if (abortOnDuplicatedAssembly)
                    {
                        Logger.LogAs(this, LogLevel.Warning, "Trying to load assembly that has been already loaded.");
                        return(false);
                    }
                    var description = assemblyFromTypeName[fullName];
                    assemblyFromTypeName.Remove(fullName);
                    assembliesFromTypeName.Add(fullName, new List <AssemblyDescription> {
                        description, newAssemblyDescription
                    });
                    continue;
                }
                assemblyFromTypeName.Add(fullName, newAssemblyDescription);
            }

            return(true);
        }