예제 #1
0
 /// <summary>
 ///     Add assemblies at runtime to the package.  Does not load the assembly into the node library.
 ///     If the package is already present in LoadedAssemblies, this will mutate it's IsNodeLibrary property.
 /// </summary>
 /// <param name="assems">A list of assemblies</param>
 internal void AddAssemblies(IEnumerable <PackageAssembly> assems)
 {
     foreach (var assem in assems)
     {
         var existingAssem = LoadedAssemblies.FirstOrDefault(x => x.Assembly.GetName().Name == assem.Assembly.GetName().Name);
         if (existingAssem != null)
         {
             existingAssem.IsNodeLibrary = assem.IsNodeLibrary;
         }
         else
         {
             LoadedAssemblies.Add(assem);
         }
     }
 }
예제 #2
0
        public AssetTypeValueField GetConcatMonoBaseField(AssetContainer cont, string managedPath)
        {
            AssetsFile file = cont.FileInstance.file;
            AssetTypeTemplateField baseTemp = new AssetTypeTemplateField();
            baseTemp.FromClassDatabase(am.classFile, AssetHelper.FindAssetClassByID(am.classFile, cont.ClassId), 0);
            AssetTypeInstance mainAti = new AssetTypeInstance(baseTemp, cont.FileReader, cont.FilePosition);
            ushort scriptIndex = cont.MonoId;
            if (scriptIndex != 0xFFFF)
            {
                AssetContainer monoScriptCont = GetAssetContainer(cont.FileInstance, mainAti.GetBaseField().Get("m_Script"), false);
                if (monoScriptCont == null)
                    return null;

                AssetTypeValueField scriptBaseField = monoScriptCont.TypeInstance.GetBaseField();
                string scriptName = scriptBaseField.Get("m_Name").GetValue().AsString();
                string scriptNamespace = scriptBaseField.Get("m_Namespace").GetValue().AsString();
                string assemblyName = scriptBaseField.Get("m_AssemblyName").GetValue().AsString();
                string assemblyPath = Path.Combine(managedPath, assemblyName);

                if (scriptNamespace != string.Empty)
                    scriptName = scriptNamespace + "." + scriptName;

                if (File.Exists(assemblyPath))
                {
                    AssemblyDefinition asmDef;

                    if (!LoadedAssemblies.ContainsKey(assemblyName))
                    {
                        LoadedAssemblies.Add(assemblyName, MonoDeserializer.GetAssemblyWithDependencies(assemblyPath));
                    }
                    asmDef = LoadedAssemblies[assemblyName];

                    MonoDeserializer mc = new MonoDeserializer();
                    mc.Read(scriptName, asmDef, file.header.format);
                    List<AssetTypeTemplateField> monoTemplateFields = mc.children;

                    AssetTypeTemplateField[] templateField = baseTemp.children.Concat(monoTemplateFields).ToArray();
                    baseTemp.children = templateField;
                    baseTemp.childrenCount = baseTemp.children.Length;

                    mainAti = new AssetTypeInstance(baseTemp, cont.FileReader, cont.FilePosition);
                }
            }
            return mainAti.GetBaseField();
        }
예제 #3
0
        private void LoadAssemblies(IEnumerable <string> paths, IEnumerable <string> skipPatterns)
        {
            foreach (var path in paths)
            {
                if (skipPatterns != null && CheckPattern(skipPatterns, path))
                {
                    continue;
                }

                try
                {
                    var asmCat = new AssemblyCatalog(path, GlobalRegistrationBuilder.Builder);

                    // Force MEF to load the plugin and figure out if there are any exports
                    // good assemblies will not throw the RTLE exception and can be added to the catalog
                    if (asmCat.Parts.Any())
                    {
                        if (CheckAlreadyLoaded(path))
                        {
                            continue;
                        }

                        _catalog.Catalogs.Add(asmCat);
                        LoadedAssemblies.Add(path);
                    }
                }
                catch (ReflectionTypeLoadException e)
                {
                    var typesStringBuilder = new StringBuilder();
                    foreach (var type in e.Types)
                    {
                        typesStringBuilder.Append(type);
                    }

                    _logger.WarnFormat("Could not load assembly '{0}' . Depending types: {1}", e, typesStringBuilder);

                    foreach (var ex in e.LoaderExceptions)
                    {
                        _logger.WarnFormat("LoaderException: '{0}'", ex);
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        ///     Enumerates all assemblies in the package
        /// </summary>
        /// <returns>The list of all node library assemblies</returns>
        internal IEnumerable <PackageAssembly> EnumerateAssembliesInBinDirectory()
        {
            var assemblies = new List <PackageAssembly>();

            if (!Directory.Exists(BinaryDirectory))
            {
                return(assemblies);
            }

            // Use the pkg header to determine which assemblies to load and prevent multiple enumeration
            // In earlier packages, this field could be null, which is correctly handled by IsNodeLibrary
            var nodeLibraries = Header.node_libraries;

            foreach (var assemFile in (new System.IO.DirectoryInfo(BinaryDirectory)).EnumerateFiles("*.dll"))
            {
                Assembly assem;

                // dll files may be un-managed, skip those
                var result = PackageLoader.TryLoadFrom(assemFile.FullName, out assem);
                if (result)
                {
                    // IsNodeLibrary may fail, we store the warnings here and then show
                    IList <ILogMessage> warnings = new List <ILogMessage>();

                    assemblies.Add(new PackageAssembly()
                    {
                        Assembly      = assem,
                        IsNodeLibrary = IsNodeLibrary(nodeLibraries, assem.GetName(), ref warnings)
                    });

                    warnings.ToList().ForEach(this.Log);
                }
            }

            foreach (var assem in assemblies)
            {
                LoadedAssemblies.Add(assem);
            }

            return(assemblies);
        }
예제 #5
0
        private Assembly HandleLoadedAssembly(Assembly assembly)
        {
            if (LoadedAssemblies.Contains(assembly))
            {
                return(assembly);
            }
            LoadedAssemblies.Add(assembly);

            foreach (var dependentAssemblyname in assembly.GetReferencedAssemblies())
            {
                Assembly dependentAssembly;
                try
                {
                    dependentAssembly = Load(dependentAssemblyname);
                }
                catch
                {
                    continue;
                }
                HandleLoadedAssembly(dependentAssembly);
            }
            return(assembly);
        }
예제 #6
0
        public static void Start(IEnumerable <CompilerResult> compiledScripts)
        {
            if (Running)
            {
                return;
            }

            Running = true;

            appDomain = AppDomain.CreateDomain("sharpyson");

            appDomain.AssemblyResolve += AppDomainOnAssemblyResolve;

            foreach (var compiledScript in compiledScripts)
            {
                var assemblyName = AssemblyName.GetAssemblyName(compiledScript.AssemblyPath);

                try
                {
                    if (compiledScript.AssemblyPath.EndsWith(".dll"))
                    {
                        appDomain.Load(assemblyName);
                    }
                    else
                    {
                        appDomain.ExecuteAssemblyByName(assemblyName);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }

                LoadedAssemblies.Add(assemblyName);
            }
        }
예제 #7
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);
            }
        }
예제 #8
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));
            }
        }
예제 #9
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}");
                }
            }
        }
예제 #10
0
        public static void RegisterAssembly(string assemblyPath)
        {
            var assembly = Assembly.LoadFrom(assemblyPath);

            LoadedAssemblies.Add(assembly);
        }
예제 #11
0
 public ArchiveContext(string path, ZipArchive archive, Assembly assembly)
 {
     Path    = path;
     Archive = archive;
     LoadedAssemblies.Add(assembly);
 }
예제 #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));
                }
            }
        }
예제 #13
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;
                }
            }
        }
예제 #14
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);
    }