Пример #1
0
 internal bool InUse(DynamoModel dynamoModel)
 {
     return((LoadedAssemblies.Any() || IsWorkspaceFromPackageOpen(dynamoModel) || IsCustomNodeFromPackageInUse(dynamoModel)) && Loaded);
 }
Пример #2
0
        //private Assembly AssemblyResolving(AssemblyLoadContext arg1, AssemblyName arg2)
        //{
        //    if (arg2.FullName == CurrentAssembly.FullName)
        //    {
        //        return CurrentAssembly;
        //    }
        //    var deps = DependencyContext.Default;
        //    if (deps.CompileLibraries.Any(d => d.Name == arg2.Name))
        //    {
        //        return Assembly.Load(arg2);
        //    }

        //    foreach (var item in DependencyAssemblies)
        //    {
        //        if (item.FullName == arg2.FullName)
        //        {
        //            return item;
        //        }
        //    }
        //    return null;
        //}
        private void ResolveDenpendency(Assembly assembly)
        {
            string currentName = assembly.GetName().Name;

            if (CompileLibraries == null)
            {
                CompileLibraries = new HashSet <string>();
                foreach (var item in DependencyContext.Default.CompileLibraries)
                {
                    if (!CompileLibraries.Contains(item.Name))
                    {
                        CompileLibraries.Add(item.Name);
                    }
                }
            }
            List <CompilationLibrary> dependencyCompilationLibrary = DependencyContext.Load(assembly)
                                                                     .CompileLibraries.Where(de => PluginInfos.All(m => m.Name != de.Name) && de.Name != currentName && !CompileLibraries.Contains(de.Name))
                                                                     .ToList();

            if (LoadedAssemblies == null)
            {
                LoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToDictionary(m => m.GetName().Name);
            }

            dependencyCompilationLibrary.Each(libaray =>
            {
                foreach (var item in libaray.ResolveReferencePaths(new DependencyAssemblyResolver(Path.GetDirectoryName(assembly.Location))))
                {
                    string assemblyName = AssemblyName.GetAssemblyName(item).Name;
                    if (!LoadedAssemblies.ContainsKey(assemblyName))
                    {
                        Assembly assemblyDep = AssemblyLoadContext.Default.LoadFromAssemblyPath(item);
                        DependencyAssemblies.Add(assemblyDep);
                        LoadedAssemblies.Add(assemblyName, assemblyDep);
                    }
                }
            });

            PluginDescriptor plugin = null;

            foreach (var typeInfo in assembly.DefinedTypes)
            {
                if (typeInfo.IsAbstract || typeInfo.IsInterface)
                {
                    continue;
                }

                if (PluginTypeInfo.IsAssignableFrom(typeInfo))
                {
                    plugin = new PluginDescriptor
                    {
                        PluginType        = typeInfo.AsType(),
                        Assembly          = assembly,
                        Dependency        = dependencyCompilationLibrary,
                        CurrentPluginPath = CurrentPath
                    };
                }
            }

            if (plugin != null)
            {
                PluginActivtor.LoadedPlugins.Add(plugin);
            }
        }
Пример #3
0
        /// <summary>
        ///     Applies patchers to all assemblies in the given directory and loads patched assemblies into memory.
        /// </summary>
        /// <param name="directory">Directory to load CLR assemblies from.</param>
        public void PatchAndLoad()
        {
            // First, create a copy of the assembly dictionary as the initializer can change them
            var assemblies = new Dictionary <string, AssemblyDefinition>(AssembliesToPatch, StringComparer.InvariantCultureIgnoreCase);

            // Next, initialize all the patchers
            foreach (var assemblyPatcher in PatcherPluginsSafe)
            {
                try
                {
                    assemblyPatcher.Initializer?.Invoke();
                }
                catch (Exception ex)
                {
                    Logger.LogError($"Failed to run initializer of {assemblyPatcher.TypeName}: {ex}");
                }
            }

            // Then, perform the actual patching

            var patchedAssemblies  = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);
            var resolvedAssemblies = new Dictionary <string, string>();

            // TODO: Maybe instead reload the assembly and repatch with other valid patchers?
            var invalidAssemblies = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);

            foreach (var assemblyPatcher in PatcherPluginsSafe)
            {
                foreach (string targetDll in assemblyPatcher.TargetDLLs())
                {
                    if (AssembliesToPatch.TryGetValue(targetDll, out var assembly) && !invalidAssemblies.Contains(targetDll))
                    {
                        Logger.LogInfo($"Patching [{assembly.Name.Name}] with [{assemblyPatcher.TypeName}]");

                        try
                        {
                            assemblyPatcher.Patcher?.Invoke(ref assembly);
                        }
                        catch (Exception e)
                        {
                            Logger.LogError($"Failed to run [{assemblyPatcher.TypeName}] when patching [{assembly.Name.Name}]. This assembly will not be patched. Error: {e}");
                            patchedAssemblies.Remove(targetDll);
                            invalidAssemblies.Add(targetDll);
                            continue;
                        }

                        AssembliesToPatch[targetDll] = assembly;
                        patchedAssemblies.Add(targetDll);

                        foreach (var resolvedAss in AppDomain.CurrentDomain.GetAssemblies())
                        {
                            var name = Utility.TryParseAssemblyName(resolvedAss.FullName, out var assName) ? assName.Name : resolvedAss.FullName;

                            // Report only the first type that caused the assembly to load, because any subsequent ones can be false positives
                            if (!resolvedAssemblies.ContainsKey(name))
                            {
                                resolvedAssemblies[name] = assemblyPatcher.TypeName;
                            }
                        }
                    }
                }
            }

            // Check if any patched assemblies have been already resolved by the CLR
            // If there are any, they cannot be loaded by the preloader
            var patchedAssemblyNames = new HashSet <string>(assemblies.Where(kv => patchedAssemblies.Contains(kv.Key)).Select(kv => kv.Value.Name.Name), StringComparer.InvariantCultureIgnoreCase);
            var earlyLoadAssemblies  = resolvedAssemblies.Where(kv => patchedAssemblyNames.Contains(kv.Key)).ToList();

            if (earlyLoadAssemblies.Count != 0)
            {
                Logger.LogWarning(new StringBuilder()
                                  .AppendLine("The following assemblies have been loaded too early and will not be patched by preloader:")
                                  .AppendLine(string.Join(Environment.NewLine, earlyLoadAssemblies.Select(kv => $"* [{kv.Key}] (first loaded by [{kv.Value}])").ToArray()))
                                  .AppendLine("Expect unexpected behavior and issues with plugins and patchers not being loaded.")
                                  .ToString());
            }

            // Finally, load patched assemblies into memory
            if (ConfigDumpAssemblies.Value || ConfigLoadDumpedAssemblies.Value)
            {
                if (!Directory.Exists(DumpedAssembliesPath))
                {
                    Directory.CreateDirectory(DumpedAssembliesPath);
                }

                foreach (KeyValuePair <string, AssemblyDefinition> kv in assemblies)
                {
                    string filename = kv.Key;
                    var    assembly = kv.Value;

                    if (patchedAssemblies.Contains(filename))
                    {
                        assembly.Write(Path.Combine(DumpedAssembliesPath, filename));
                    }
                }
            }

            if (ConfigBreakBeforeLoadAssemblies.Value)
            {
                Logger.LogInfo($"BepInEx is about load the following assemblies:\n{String.Join("\n", patchedAssemblies.ToArray())}");
                Logger.LogInfo($"The assemblies were dumped into {DumpedAssembliesPath}");
                Logger.LogInfo("Load any assemblies into the debugger, set breakpoints and continue execution.");
                Debugger.Break();
            }

            foreach (var kv in assemblies)
            {
                string filename = kv.Key;
                var    assembly = kv.Value;

                // Note that since we only *load* assemblies, they shouldn't trigger dependency loading
                // Not loading all assemblies is very important not only because of memory reasons,
                // but because some games *rely* on that because of messed up internal dependencies.
                if (patchedAssemblies.Contains(filename))
                {
                    Assembly loadedAssembly;

                    if (ConfigLoadDumpedAssemblies.Value)
                    {
                        loadedAssembly = Assembly.LoadFile(Path.Combine(DumpedAssembliesPath, filename));
                    }
                    else
                    {
                        using (var assemblyStream = new MemoryStream())
                        {
                            assembly.Write(assemblyStream);
                            loadedAssembly = Assembly.Load(assemblyStream.ToArray());
                        }
                    }

                    LoadedAssemblies.Add(filename, loadedAssembly);

                    Logger.LogDebug($"Loaded '{assembly.FullName}' into memory");
                }

                // Though we have to dispose of all assemblies regardless of them being patched or not
                assembly.Dispose();
            }

            // Finally, run all finalizers
            foreach (var assemblyPatcher in PatcherPluginsSafe)
            {
                try
                {
                    assemblyPatcher.Finalizer?.Invoke();
                }
                catch (Exception ex)
                {
                    Logger.LogError($"Failed to run finalizer of {assemblyPatcher.TypeName}: {ex}");
                }
            }
        }
Пример #4
0
        /// <summary>
        ///     Scans the specified paths for plugins & loads them into the AppDomain
        /// </summary>
        /// <param name="paths"></param>
        /// <exception cref="DirectoryNotFoundException"></exception>
        public void DiscoverPlugins(params string[] paths)
        {
            int pluginInstances = 0;

            paths = paths.Where(x =>
            {
                if (Directory.Exists(x))
                {
                    return(true);
                }
                else
                {
                    Log.Warn($"Could not load plugins from folder \"{x}\", folder does not exist!");
                    return(false);
                }
            }).ToArray();

            foreach (var path in paths)
            {
                if (!Directory.Exists(path))
                {
                    throw new DirectoryNotFoundException("Directory not found: " + path);
                }
            }

            Dictionary <Assembly, string> loadedAssemblies = new Dictionary <Assembly, string>();
            //List<(Assembly assembly, string path)> loadedAssemblies = new List<(Assembly assembly, string path)>();
            int processed = 0;

            foreach (var rawPath in paths)
            {
                string path = rawPath;

                string[] files = Directory.GetFiles(path, "*.dll", SearchOption.AllDirectories);
                foreach (string file in files)
                {
                    try
                    {
                        string filename = Path.GetFileNameWithoutExtension(file);
                        if (!Config.GetProperty($"plugin.{filename}.enabled", true))
                        {
                            Log.Info($"Not loading \"{Path.GetRelativePath(rawPath, file)}\" as it was disabled by config.");
                            continue;
                        }

                        path = Path.GetDirectoryName(file);

                        Assembly[] result;
                        ProcessFile(path, file, out result);
                        processed++;

                        if (result == null)
                        {
                            continue;
                        }

                        foreach (var assembly in result)
                        {
                            if (!loadedAssemblies.ContainsKey(assembly))
                            {
                                loadedAssemblies.Add(assembly, path);
                            }
                        }
                    }
                    catch (BadImageFormatException ex)
                    {
                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug($"File is not a .NET Assembly ({file})", ex);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error($"Failed loading \"{file}\"", ex);
                    }
                }
            }

            Log.Info($"Loaded {loadedAssemblies.Count} assemblies from {processed} processed files.");

            //List<OpenPlugin> plugins = new List<OpenPlugin>();
            LinkedList <PluginConstructorData> constructorDatas = new LinkedList <PluginConstructorData>();

            foreach (var assembly in loadedAssemblies)
            {
                if (assembly.Key != null)
                {
                    var constructors = FindPluginConstructors(assembly.Key);
                    foreach (var constructor in constructors)
                    {
                        var existing = constructorDatas.FirstOrDefault(x => x.Type == constructor.Type);
                        if (existing != null)
                        {
                            if (!existing.ReferencesOtherPlugin && constructor.ReferencesOtherPlugin)
                            {
                                var found = constructorDatas.Find(existing);
                                if (found != null)
                                {
                                    found.Value = constructor;
                                    continue;
                                }
                            }
                        }

                        constructorDatas.AddLast(constructor);
                    }
                }
            }

            Dictionary <Assembly, List <OpenPlugin> > assemblies = new Dictionary <Assembly, List <OpenPlugin> >();

            //Load all plugins that do NOT have a reference to any other plugins.
            foreach (var grouped in constructorDatas.Where(x => !x.ReferencesOtherPlugin).GroupBy(x => x.Type.Assembly))
            {
                List <OpenPlugin> assemblyInstances = new List <OpenPlugin>();
                foreach (var constructor in grouped)
                {
                    if (CreateInstance(constructor, out OpenPlugin instance, assemblies))
                    {
                        Services.RegisterSingleton(instance.GetType(), instance);
                        pluginInstances++;

                        assemblyInstances.Add(instance);
                    }
                }

                if (!assemblies.ContainsKey(grouped.Key))
                {
                    assemblies.Add(grouped.Key, assemblyInstances);
                }
                else
                {
                    assemblies[grouped.Key].AddRange(assemblyInstances);
                }
            }

            LinkedList <PluginConstructorData> ordered = new LinkedList <PluginConstructorData>();

            var requiresOthers = constructorDatas.Where(x => x.ReferencesOtherPlugin).ToArray();

            foreach (var grouped in requiresOthers)
            {
                var thisNode = ordered.Find(grouped);
                if (thisNode == null)
                {
                    thisNode = ordered.AddLast(grouped);
                }

                var otherPlugins = grouped.Dependencies.Where(x => x.IsPluginInstance).Select(x => x.Type).ToArray();
                foreach (var otherDependency in otherPlugins)
                {
                    var found = requiresOthers.FirstOrDefault(x => x.Type == otherDependency);
                    if (found != null)
                    {
                        ordered.AddBefore(thisNode, found);
                    }
                }
            }

            bool done = false;

            var current = ordered.First;

            do
            {
                var currentValue = current?.Value;
                var next         = current?.Next;
                if (next == null || currentValue == null)
                {
                    done = true;
                    break;
                }

                if (currentValue.Requires(next.Value))
                {
                    current.Value = next.Value;
                    next.Value    = currentValue;
                }

                current = next;
            } while (!done);

            foreach (var item in ordered)
            {
                // List<OpenPlugin> assemblyInstances = new List<OpenPlugin>();

                if (Services.TryResolve(item.Type, out _))
                {
                    continue;
                }

                if (CreateInstance(item, out var instance, assemblies))
                {
                    Services.RegisterSingleton(item.Type, instance);            //.Add(instance);
                    pluginInstances++;


                    if (!assemblies.ContainsKey(item.Type.Assembly))
                    {
                        assemblies.Add(item.Type.Assembly, new List <OpenPlugin>()
                        {
                            instance
                        });
                    }
                    else
                    {
                        assemblies[item.Type.Assembly].Add(instance);
                    }
                }
            }


            Log.Info($"Registered {pluginInstances} plugin instances");

            foreach (var grouped in assemblies)
            {
                LoadedAssemblies.Add(grouped.Key,
                                     new LoadedAssembly(grouped.Key, grouped.Value.Select(x => x.GetType()), new Assembly[0], grouped.Key.Location));
            }
        }
Пример #5
0
 public ArchiveContext(string path, ZipArchive archive, Assembly assembly)
 {
     Path    = path;
     Archive = archive;
     LoadedAssemblies.Add(assembly);
 }
Пример #6
0
        public static void RegisterAssembly(string assemblyPath)
        {
            var assembly = Assembly.LoadFrom(assemblyPath);

            LoadedAssemblies.Add(assembly);
        }
Пример #7
0
        /// <summary>
        /// This is called when a new assembly is loaded, we need to know this
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="args">AssemblyLoadEventArgs</param>
        private void AssemblyLoad(object sender, AssemblyLoadEventArgs args)
        {
            var loadedAssembly = args.LoadedAssembly;
            var assemblyName   = loadedAssembly.GetName().Name;

            if (Log.IsVerboseEnabled())
            {
                Log.Verbose().WriteLine("Loaded {0}", assemblyName);
            }
            LoadedAssemblies[assemblyName] = loadedAssembly;

            if (!_applicationConfig.ScanForEmbeddedAssemblies)
            {
                return;
            }

            // Ignore resource checking on certain assemblies
            if (AssembliesToIgnore.IsMatch(assemblyName))
            {
                return;
            }

            string[] resources;
            try
            {
                resources = Resources.GetCachedManifestResourceNames(loadedAssembly);
            }
            catch (Exception ex)
            {
                Log.Warn().WriteLine(ex, "Couldn't retrieve resources from {0}", loadedAssembly.GetName().Name);
                return;
            }
            foreach (var resource in resources)
            {
                var resourceMatch = _assemblyResourceNameRegex.Match(resource);
                if (!resourceMatch.Success)
                {
                    continue;
                }

                var embeddedAssemblyName = resourceMatch.Groups["assembly"].Value;
                if (LoadedAssemblies.ContainsKey(embeddedAssemblyName))
                {
                    // Ignoring already loaded assembly, as we cannot unload.
                    continue;
                }
                var newAssemblyLocation = new AssemblyLocationInformation(embeddedAssemblyName, loadedAssembly, resource);
                if (AvailableAssemblies.TryGetValue(embeddedAssemblyName, out var availableAssemblyLocationInformation))
                {
                    if (availableAssemblyLocationInformation.FileDate > newAssemblyLocation.FileDate)
                    {
                        continue;
                    }
                }
                if (Log.IsVerboseEnabled())
                {
                    Log.Verbose().WriteLine("Detected additional assembly {0} in {1}", embeddedAssemblyName, loadedAssembly.GetName().Name);
                }
                AvailableAssemblies[embeddedAssemblyName] = newAssemblyLocation;
            }
        }
Пример #8
0
 public IEnumerable <Type> GetTypes <T>()
 {
     return(LoadedAssemblies.SelectMany(ass => ass.Types)
            .Where(t => typeof(T).IsAssignableFrom(t)).ToList());
 }
Пример #9
0
        /// <summary>
        /// Do the one time scan of all the assemblies
        /// </summary>
        private void ScanForAssemblies()
        {
            var assemblies = new HashSet <AssemblyLocationInformation>();

            if (_applicationConfig.ScanForEmbeddedAssemblies)
            {
                foreach (var loadedAssembly in LoadedAssemblies.Where(pair => !AssembliesToIgnore.IsMatch(pair.Key)).Select(pair => pair.Value).ToList())
                {
                    string[] resources;
                    try
                    {
                        resources = Resources.GetCachedManifestResourceNames(loadedAssembly);
                    }
                    catch (Exception ex)
                    {
                        Log.Warn().WriteLine(ex, "Couldn't retrieve resources from {0}", loadedAssembly.GetName().Name);
                        continue;
                    }
                    foreach (var resource in resources)
                    {
                        var resourceMatch = _assemblyResourceNameRegex.Match(resource);
                        if (resourceMatch.Success)
                        {
                            assemblies.Add(new AssemblyLocationInformation(resourceMatch.Groups["assembly"].Value, loadedAssembly, resource));
                        }
                    }
                }
            }

            if (_applicationConfig.UseStrictChecking)
            {
                foreach (var applicationConfigScanDirectory in _applicationConfig.ScanDirectories)
                {
                    if (!Directory.Exists(applicationConfigScanDirectory))
                    {
                        throw new DirectoryNotFoundException(applicationConfigScanDirectory);
                    }
                }
            }
            foreach (var fileLocation in FileLocations.Scan(_applicationConfig.ScanDirectories, _assemblyFilenameRegex, SearchOption.TopDirectoryOnly))
            {
                assemblies.Add(new AssemblyLocationInformation(fileLocation.Item2.Groups["assembly"].Value, fileLocation.Item1));
            }

            // Reduce step 1) Take from the double assemblies only those which are embedded & on the file system in the probing path
            foreach (var assemblyGroup in assemblies.GroupBy(information => information.Name).ToList())
            {
                var groupList = assemblyGroup.ToList();
                if (groupList.Count <= 1)
                {
                    continue;
                }

                // Remove filesystem assemblies from the list which are not in the AssemblyResolveDirectories
                var unneededAssemblies = groupList.Where(info => !info.IsEmbedded && !info.IsOnProbingPath).ToList();
                if (groupList.Count - unneededAssemblies.Count < 1)
                {
                    continue;
                }

                foreach (var unneededAssemblyInformation in unneededAssemblies)
                {
                    assemblies.Remove(unneededAssemblyInformation);
                }
            }

            // Reduce step 2)
            foreach (var assemblyGroup in assemblies.GroupBy(information => information.Name).ToList())
            {
                var groupList = assemblyGroup.ToList();
                if (groupList.Count <= 1)
                {
                    continue;
                }
                // Remove assemblies which are older
                foreach (var unneededAssemblyInformation in groupList.OrderBy(info => info.FileDate).Skip(1).ToList())
                {
                    assemblies.Remove(unneededAssemblyInformation);
                }
            }

            // Create the assembly locations
            foreach (var assemblyLocationInformation in assemblies)
            {
                AvailableAssemblies[assemblyLocationInformation.Name] = assemblyLocationInformation;
            }
        }
Пример #10
0
        /// <summary>
        /// Load an assembly via a file, this used via Assembly.Load or Assembly.LoadFrom depending on where the file is or can be stored
        /// </summary>
        /// <param name="additionalInformation">AssemblyLocationInformation used for some decisions</param>
        /// <returns>Assembly</returns>
        private Assembly LoadFromFile(AssemblyLocationInformation additionalInformation)
        {
            // Get the assembly name from the file
            var assemblyName = AssemblyName.GetAssemblyName(additionalInformation.Filename);

            // Check the cache again, this time with the "real" name
            if (LoadedAssemblies.TryGetValue(assemblyName.Name, out var assembly))
            {
                if (Log.IsInfoEnabled())
                {
                    Log.Info().WriteLine("Returned {0} from cache.", assemblyName.Name);
                }
                return(assembly);
            }

            var destination            = $@"{FileLocations.AddonsLocation}\{assemblyName.Name}.dll";
            var destinationIsNotSource = !destination.Equals(additionalInformation.Filename, StringComparison.OrdinalIgnoreCase);

            if (Log.IsDebugEnabled() && !destinationIsNotSource)
            {
                Log.Debug().WriteLine("Skipping copy, as destination and source would be the same.");
            }
            if (_applicationConfig.CopyAssembliesToProbingPath && FileLocations.AddonsLocation != null && destinationIsNotSource)
            {
                try
                {
                    if (ShouldWrite(additionalInformation, destination))
                    {
                        if (Log.IsVerboseEnabled())
                        {
                            Log.Verbose().WriteLine("Creating a copy of {0} to {1}, solving potential context loading issues.", additionalInformation.Filename, destination);
                        }
                        File.Copy(additionalInformation.Filename, destination);
                        // Register delete on exit, this is done by calling a command
                        _assembliesToDeleteAtExit.Add(destination);
                    }
                    // Load via the assembly name, it's not inside the probing path
                    assembly = Assembly.Load(assemblyName);
                    if (assembly != null)
                    {
                        return(assembly);
                    }
                }
                catch (Exception ex)
                {
                    Log.Warn().WriteLine(ex, "Couldn't create a copy of {0} to {1}.", additionalInformation.Filename, destination);
                }
            }

            if (Log.IsVerboseEnabled())
            {
                Log.Verbose().WriteLine("Loading {0} from {1}.", additionalInformation.Name, additionalInformation.Filename);
            }

            try
            {
                return(Assembly.LoadFrom(additionalInformation.Filename));
            }
            catch (Exception ex)
            {
                Log.Error().WriteLine(ex, "Couldn't load assembly from file {0}", additionalInformation.Filename);
            }
            return(null);
        }
Пример #11
0
 internal void InitialiseDependencyResolvers()
 {
     _dependencyResolvers = LoadedAssemblies.Select(x => new DependencyResolver(x.Value)).ToList();
 }
Пример #12
0
        public void LoadPlugins()
        {
            int pluginInstances = 0;

            Dictionary <Assembly, List <Plugin> > assemblies = new Dictionary <Assembly, List <Plugin> >();

            //Load all plugins that do NOT have a reference to any other plugins.
            foreach (var grouped in PluginConstructors.Where(x => !x.ReferencesOtherPlugin).GroupBy(x => x.Type.Assembly).ToArray())
            {
                List <Plugin> assemblyInstances = new List <Plugin>();
                foreach (var constructor in grouped)
                {
                    if (CreateInstance(constructor, out Plugin instance, assemblies))
                    {
                        PluginContainer.RegisterSingleton(instance.GetType(), instance);
                        pluginInstances++;

                        assemblyInstances.Add(instance);
                    }

                    PluginConstructors.Remove(constructor);
                }

                if (!assemblies.ContainsKey(grouped.Key))
                {
                    assemblies.Add(grouped.Key, assemblyInstances);
                }
                else
                {
                    assemblies[grouped.Key].AddRange(assemblyInstances);
                }
            }

            LinkedList <PluginConstructorData> ordered = new LinkedList <PluginConstructorData>();

            var requiresOthers = PluginConstructors.Where(x => x.ReferencesOtherPlugin).ToArray();

            foreach (var grouped in requiresOthers)
            {
                var thisNode = ordered.Find(grouped);
                if (thisNode == null)
                {
                    thisNode = ordered.AddLast(grouped);
                }

                var otherPlugins = grouped.Dependencies.Where(x => x.IsPluginInstance).Select(x => x.Type).ToArray();
                foreach (var otherDependency in otherPlugins)
                {
                    var found = requiresOthers.FirstOrDefault(x => x.Type == otherDependency);
                    if (found != null)
                    {
                        ordered.AddBefore(thisNode, found);
                    }
                }
            }

            bool done = false;

            var current = ordered.First;

            do
            {
                var currentValue = current?.Value;
                var next         = current?.Next;
                if (next == null || currentValue == null)
                {
                    done = true;
                    break;
                }

                if (currentValue.Requires(next.Value))
                {
                    current.Value = next.Value;
                    next.Value    = currentValue;
                }

                current = next;
            } while (!done);

            foreach (var item in ordered)
            {
                // List<OpenPlugin> assemblyInstances = new List<OpenPlugin>();

                if (PluginContainer.TryResolve(item.Type, out _))
                {
                    continue;
                }

                if (CreateInstance(item, out var instance, assemblies))
                {
                    PluginContainer.RegisterSingleton(item.Type, instance);            //.Add(instance);
                    pluginInstances++;


                    if (!assemblies.ContainsKey(item.Type.Assembly))
                    {
                        assemblies.Add(item.Type.Assembly, new List <Plugin>()
                        {
                            instance
                        });
                    }
                    else
                    {
                        assemblies[item.Type.Assembly].Add(instance);
                    }
                }
            }


            Log.Info($"Registered {pluginInstances} plugin instances");

            foreach (var grouped in assemblies)
            {
                if (LoadedAssemblies.ContainsKey(grouped.Key))
                {
                    LoadedAssemblies[grouped.Key].PluginTypes.AddRange(grouped.Value.Select(x => x.GetType()));
                    continue;
                }
                else
                {
                    LoadedAssemblies.Add(grouped.Key,
                                         new LoadedAssembly(grouped.Key, grouped.Value.Select(x => x.GetType()), new Assembly[0],
                                                            grouped.Key.Location));
                }
            }
        }
        private Type GetExceptionType(RpcErrorTypeBehavior typeResolution)
        {
            Type     tException = typeof(ApplicationException);
            Assembly found      = tException.Assembly;

            if (typeResolution == RpcErrorTypeBehavior.NoTypeResolution)
            {
                return(tException);
            }

            if (!HasFullTypeName || !HasAssemblyName || String.IsNullOrEmpty(FullTypeName) ||
                String.IsNullOrEmpty(AssemblyName))
            {
                return(tException);
            }

            if (!ValidTypeName.IsMatch(FullTypeName))
            {
                return(tException);
            }

            if (typeResolution == RpcErrorTypeBehavior.OnlyUseMsCorLibTypes)
            {
                return(found.GetType(FullTypeName) ?? tException);
            }

            AssemblyName name = new AssemblyName(AssemblyName);

            if (name.CodeBase != null)
            {
                return(tException);
            }

            if (null != (found = LoadedAssemblies.Lookup(name)))
            {
                return(found.GetType(FullTypeName) ?? tException);
            }

            if (typeResolution == RpcErrorTypeBehavior.OnlyUseLoadedAssemblies)
            {
                return(tException);
            }

            if (typeResolution == RpcErrorTypeBehavior.OnlyLoadStrongNamed && name.GetPublicKeyToken() == null)
            {
                return(tException);
            }

            Type test = Type.GetType(String.Format("{0}, {1}", FullTypeName, name));

            if (test != null)
            {
                return(test);
            }

            if (typeResolution == RpcErrorTypeBehavior.LoadAnyAssembly)
            {
                return(Type.GetType(String.Format("{0}, {1}", FullTypeName, new AssemblyName(name.Name))) ?? tException);
            }

            return(tException);
        }
Пример #14
0
        internal static void Run()
        {
            JEMLogger.Log("Loading appcfg.", "APP");
            AppConfig.LoadConfiguration();

            if (!Directory.Exists(AssembliesDirectory))
            {
                JEMLogger.LogError($"Assemblies directory `{AssembliesDirectory}` does not exist.", "APP");
                return;
            }

            var assembliesTargets = AssembliesDirectory + JEMVar.DirectorySeparatorChar + AppConfig.Loaded.AssembliesTargetsFile;

            if (!File.Exists(assembliesTargets))
            {
                JEMLogger.LogError($"File defining target assemblies `{assembliesTargets}` does not exist.", "APP");
                return;
            }

            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {
                JEMLogger.LogError("Failed to resolve assembly " + args.Name, "APP");
                return(Assembly.LoadFrom(args.Name));
            };

            AssembliesNames = File.ReadAllLines(assembliesTargets);
            JEMLogger.Log($"{AssembliesNames.Length} target assemblies found.", "APP");
            foreach (var a in AssembliesNames)
            {
                JEMLogger.Log($"\t{a}", "APP");
            }
            Console.WriteLine();

            if (Directory.Exists(DeployDirectory))
            {
                Directory.Delete(DeployDirectory, true);
            }

            Directory.CreateDirectory(DeployDirectory);

            foreach (var a in AssembliesNames)
            {
                var          file         = AssembliesDirectory + JEMVar.DirectorySeparatorChar + a + ".dll";
                AssemblyName assemblyName = null;
                try
                {
                    assemblyName = AssemblyName.GetAssemblyName(file);
                }
                catch (Exception e)
                {
                    JEMLogger.LogException(e, "APP");
                }

                var assembly = assemblyName == null ? null : Assembly.Load(assemblyName);
                if (assembly == null)
                {
                    JEMLogger.LogError($"Unable to load assembly `{file}`", "APP");
                }
                else
                {
                    JEMLogger.Log($"Assembly {file} loaded..", "APP");
                    LoadedAssemblies.Add(assembly);
                }
            }

            JEMLogger.Log("Generating.", "APP");
            foreach (var assembly in LoadedAssemblies)
            {
                try
                {
                    GenerateOffAssembly(assembly);
                }
                catch (TypeLoadException e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            }
        }
Пример #15
0
    /*public delegate void AssemblyLoadedHandler(AssemblyLoadedEventArgs args);
     *
     * public class AssemblyLoadedEventArgs
     * {
     *      public Assembly Assembly { get; private set; }
     *
     *      public AssemblyLoadedEventArgs(Assembly assembly)
     *      {
     *              Assembly = assembly;
     *      }
     * }
     *
     * public event AssemblyLoadedHandler AssemblyLoaded;
     *
     * private void OnAssemblyLoaded(Assembly assem)
     * {
     *      if (AssemblyLoaded != null)
     *      {
     *              AssemblyLoaded(new AssemblyLoadedEventArgs(assem));
     *      }
     * }
     */

    /// <summary>
    /// Load all types which inherit from NodeModel whose assemblies are located in
    /// the bin/nodes directory. Add the types to the searchviewmodel and
    /// the controller's dictionaries.
    /// </summary>
    public virtual List <Type> LoadNodeModels(string folderToSearch, bool searchAppDomain)
    {
        var loadedAssembliesByPath = new Dictionary <string, Assembly>();
        var loadedAssembliesByName = new Dictionary <string, Assembly>();
        var allNodeAssemblies      = new List <System.Reflection.Assembly>();

        // cache the loaded assembly information
        if (searchAppDomain)
        {
            foreach (
                var assembly in
                AppDomain.CurrentDomain.GetAssemblies())
            {
                try
                {
                    loadedAssembliesByPath[assembly.Location] = assembly;
                    loadedAssembliesByName[assembly.FullName] = assembly;
                }
                catch { }
            }
            allNodeAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
        }
        var loadedTypes = new List <Type>();

        // going to look in all currently loaded assemblies for nodes, then we'll also look
        // in a specific folder of the resources or data folder, unsure on this path yet...

        string path = Application.dataPath;

        Debug.Log(path);
        path = Path.Combine(path, folderToSearch);
        Debug.Log(path);
        List <Assembly> allAssembliesinbuild = new List <Assembly>();

        foreach (string dll in Directory.GetFiles(path, "*.dll"))
        {
            allAssembliesinbuild.Add(Assembly.LoadFile(dll));
        }

        allNodeAssemblies.AddRange(allAssembliesinbuild);

        //iterate each assembly location
        foreach (var assemblyPath in allNodeAssemblies.Select(x => x.Location).ToList())
        {
            Debug.Log("current assembly path is " + assemblyPath);
            //get the filename at each location and check it's not null
            var fn = Path.GetFileName(assemblyPath);
            if (fn == null)
            {
                continue;
            }
            Debug.Log("filename is " + fn);
            // if the assembly has already been loaded, then
            // skip it, otherwise cache it.
            if (LoadedAssemblyNames.Contains(fn))
            {
                continue;
            }

            LoadedAssemblyNames.Add(fn);

            try
            {
                Assembly assembly;
                if (!loadedAssembliesByPath.TryGetValue(assemblyPath, out assembly))
                {
                    Debug.Log("about to load assembly from" + assemblyPath);
                    assembly = Assembly.LoadFrom(assemblyPath);
                    loadedAssembliesByName[assembly.GetName().Name] = assembly;
                    loadedAssembliesByPath[assemblyPath]            = assembly;
                }

                loadedTypes.AddRange(LoadNodesFromAssembly(assembly));
                LoadedAssemblies.Add(assembly);
                //TODO possibly readd event that fires when assemlbly loaded
                //OnAssemblyLoaded(assembly);
            }
            catch (BadImageFormatException)
            {
                //swallow these warnings.
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
        }

        //AppDomain.CurrentDomain.AssemblyResolve -= resolver;
        return(loadedTypes);
    }